@jbrowse/bandage-core 11.7.3 → 11.9.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.
- package/README.md +59 -19
- package/dist/bubbles/bubbleHalos.js +6 -6
- package/dist/bubbles/classifyBubble.js +5 -5
- package/dist/bubbles/superbubbles.js +7 -7
- package/dist/chunks/{chunk-K4KVAMEF.js → chunk-2A6Z2DHF.js} +1 -1
- package/dist/chunks/{chunk-4SN7R4UF.js → chunk-2MXFG3W7.js} +1 -1
- package/dist/chunks/chunk-3BDQQTXY.js +568 -0
- package/dist/chunks/{chunk-QXBQDHKL.js → chunk-3BOREHCJ.js} +80 -38
- package/dist/chunks/{chunk-F4CDC72I.js → chunk-3DHGSHC3.js} +1 -1
- package/dist/chunks/{chunk-P276TWPM.js → chunk-3GORESBG.js} +1 -1
- package/dist/chunks/{chunk-4KOYS5WR.js → chunk-4BYGFDQB.js} +1 -1
- package/dist/chunks/{chunk-LH436HS2.js → chunk-4JDO7ZLN.js} +2 -2
- package/dist/chunks/{chunk-2US43KNG.js → chunk-7YSIP3O2.js} +2 -2
- package/dist/chunks/{chunk-VNF236GG.js → chunk-ARXDNQLF.js} +2 -2
- package/dist/chunks/{chunk-N73RA4DR.js → chunk-AURNOR27.js} +3 -3
- package/dist/chunks/{chunk-63XWYNID.js → chunk-BDS5VZYZ.js} +4 -4
- package/dist/chunks/{chunk-BXE3SBBN.js → chunk-C3KAPREU.js} +1 -1
- package/dist/chunks/{chunk-VXKL2ZLR.js → chunk-GDZQFELP.js} +259 -60
- package/dist/chunks/{chunk-2T3V6Z3M.js → chunk-GYJMPVOU.js} +1 -1
- package/dist/chunks/{chunk-BFUS3ENH.js → chunk-HEYIAMTC.js} +2 -2
- package/dist/chunks/{chunk-HMEAGAGC.js → chunk-HIN56TLA.js} +2 -2
- package/dist/chunks/{chunk-2VMKQKVO.js → chunk-HNNP5QUN.js} +1 -1
- package/dist/chunks/{chunk-W5YRBEWQ.js → chunk-I53QYITQ.js} +1 -1
- package/dist/chunks/{chunk-UTDMFVC7.js → chunk-I5CHAYDZ.js} +8 -8
- package/dist/chunks/{chunk-EPOPGV5G.js → chunk-IXLT3JJX.js} +1 -1
- package/dist/chunks/{chunk-SG7VQB4F.js → chunk-IZKM4NY7.js} +1 -1
- package/dist/chunks/{chunk-KMLATBNT.js → chunk-J7RNXBXA.js} +3 -3
- package/dist/chunks/{chunk-VACK24HF.js → chunk-JJV2GT2Z.js} +43 -9
- package/dist/chunks/{chunk-PKGPSTRW.js → chunk-JO2T77NW.js} +2 -2
- package/dist/chunks/{chunk-XKPXOIWD.js → chunk-JVT3XTKN.js} +3 -3
- package/dist/chunks/{chunk-SDI6BVG7.js → chunk-KKHXMJEE.js} +1 -1
- package/dist/chunks/{chunk-G7SG4XMK.js → chunk-LODKC7PJ.js} +7 -0
- package/dist/chunks/{chunk-AJQRKN3X.js → chunk-N3DCLT7M.js} +1 -1
- package/dist/chunks/{chunk-ZZZ6NVLW.js → chunk-NAYS472K.js} +1 -1
- package/dist/chunks/{chunk-AWJJSA7D.js → chunk-NWEVR2OQ.js} +1 -1
- package/dist/chunks/{chunk-33KUO34R.js → chunk-P2GJBFNA.js} +1 -1
- package/dist/chunks/{chunk-IHM43Y7B.js → chunk-RT4U3DH3.js} +1 -1
- package/dist/chunks/{chunk-XTCIKBWM.js → chunk-S6E3PMH7.js} +1 -1
- package/dist/chunks/{chunk-BLDUBB7X.js → chunk-SZYFZNCO.js} +2 -2
- package/dist/chunks/{chunk-T3MEG5D3.js → chunk-T2UNTWU5.js} +90 -21
- package/dist/chunks/{chunk-QJC63NFR.js → chunk-TQ26XEFL.js} +2 -2
- package/dist/chunks/{chunk-6RB5ZQ34.js → chunk-UEWIGD52.js} +51 -14
- package/dist/chunks/{chunk-SENPGW4O.js → chunk-VCUOYVLC.js} +1 -1
- package/dist/chunks/{chunk-CL6ELLVF.js → chunk-VNCHWWLG.js} +1 -1
- package/dist/chunks/{chunk-GD6RUZU5.js → chunk-VQ353UDK.js} +14 -8
- package/dist/chunks/{chunk-QLLKALSH.js → chunk-VTGQCLGI.js} +1 -1
- package/dist/chunks/{chunk-Z4HXW6ZH.js → chunk-ZWBQ4RRK.js} +24 -10
- package/dist/cli/figure.js +31 -30
- package/dist/cli/fold.js +6 -6
- package/dist/deletionEdges.js +2 -2
- package/dist/figure.js +27 -26
- package/dist/figureData.js +25 -24
- package/dist/figureScene.js +18 -17
- package/dist/figureSettings.js +6 -6
- package/dist/foldVariants.js +2 -2
- package/dist/genes/genePins.js +3 -3
- package/dist/graphLabels.js +4 -4
- package/dist/index.js +45 -44
- package/dist/labelLayout.js +8 -8
- package/dist/layout/forceCache.js +6 -6
- package/dist/layout/mergeRuns.js +2 -2
- package/dist/layout/orientToReference.js +2 -2
- package/dist/layout/tubeMapLayout.js +9 -9
- package/dist/layout/walkRowDraw.js +9 -8
- package/dist/layout/walkRowLayout.js +3 -3
- package/dist/layout/walkRowRuns.js +1 -1
- package/dist/layout/walkRows.js +2 -2
- package/dist/layout/walkStrip.js +13 -12
- package/dist/layoutModes.js +11 -11
- package/dist/pathColors.js +5 -5
- package/dist/pipeline.js +5 -5
- package/dist/referenceStrip.js +9 -8
- package/dist/renderer/GeometryBuilder.js +8 -7
- package/dist/renderer/walkLanes.js +46 -0
- package/dist/tubeMap/axis.js +5 -5
- package/dist/tubeMap/bundle.js +10 -10
- package/dist/tubeMap/coarsen.js +10 -10
- package/dist/tubeMap/deviations.js +11 -11
- package/dist/tubeMap/draw.js +5 -5
- package/dist/tubeMap/genes.js +6 -6
- package/dist/tubeMap/nodeColors.js +9 -8
- package/dist/tubeMap/reads.js +2 -2
- package/dist/types/figureData.d.ts +22 -0
- package/dist/types/renderer/types.d.ts +20 -0
- package/dist/types/renderer/walkLanes.d.ts +76 -0
- package/dist/types/util/geometry.d.ts +13 -1
- package/dist/types/version.d.ts +1 -1
- package/dist/types/walkEncoding.d.ts +9 -5
- package/dist/types/walkHighlight.d.ts +3 -0
- package/dist/util/SpatialIndex.js +4 -4
- package/dist/util/edgeCurves.js +3 -3
- package/dist/util/geometry.js +7 -1
- package/dist/util/hitDetection.js +5 -5
- package/dist/version.js +1 -1
- package/dist/viewport.js +6 -6
- package/dist/walkEncoding.js +13 -10
- package/dist/walkHighlight.js +10 -9
- package/dist/walkKey.js +5 -5
- package/package.json +1 -1
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
import {
|
|
2
|
+
THREAD_PITCH_PX,
|
|
3
|
+
THREAD_PX,
|
|
4
|
+
bandScale,
|
|
5
|
+
bandWidthPx,
|
|
6
|
+
laneSlideAt,
|
|
7
|
+
liftLanes,
|
|
8
|
+
slotCentres,
|
|
9
|
+
threadsPasses
|
|
10
|
+
} from "./chunk-3BDQQTXY.js";
|
|
1
11
|
import {
|
|
2
12
|
abgrToCssRgba,
|
|
3
13
|
fadeAbgr,
|
|
@@ -10,13 +20,13 @@ import {
|
|
|
10
20
|
} from "./chunk-GQZVR5DW.js";
|
|
11
21
|
import {
|
|
12
22
|
baseEdgeCurves
|
|
13
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-P2GJBFNA.js";
|
|
14
24
|
import {
|
|
15
25
|
PATH_LIGHTNESS,
|
|
16
26
|
PATH_SATURATION,
|
|
17
27
|
nameHue,
|
|
18
28
|
pathHueAt
|
|
19
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-VQ353UDK.js";
|
|
20
30
|
import {
|
|
21
31
|
meanDepth,
|
|
22
32
|
nodeWidthPx,
|
|
@@ -26,13 +36,17 @@ import {
|
|
|
26
36
|
referenceMidpoints
|
|
27
37
|
} from "./chunk-VX656OAZ.js";
|
|
28
38
|
import {
|
|
29
|
-
|
|
39
|
+
weakMemo
|
|
40
|
+
} from "./chunk-HMXCN6PG.js";
|
|
41
|
+
import {
|
|
42
|
+
dashSpans,
|
|
30
43
|
pathRibbonOffsets,
|
|
31
44
|
polylinePx,
|
|
45
|
+
slideCurves,
|
|
32
46
|
strandSides,
|
|
33
47
|
translateCurves,
|
|
34
48
|
yToXOf
|
|
35
|
-
} from "./chunk-
|
|
49
|
+
} from "./chunk-JJV2GT2Z.js";
|
|
36
50
|
import {
|
|
37
51
|
pushTo
|
|
38
52
|
} from "./chunk-BSOZW3FC.js";
|
|
@@ -149,13 +163,16 @@ function arrowheadFor({
|
|
|
149
163
|
color
|
|
150
164
|
};
|
|
151
165
|
}
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
const gap = (p) => Math.hypot(p.x -
|
|
166
|
+
var FIRST_THREADS = [[0, 0]];
|
|
167
|
+
var ONE_PASS = [0];
|
|
168
|
+
var NO_SHIFT = { dx: 0, dy: 0 };
|
|
169
|
+
function nearerStart(at, segments, yToX) {
|
|
170
|
+
const gap = (p) => Math.hypot(p.x - at.x, (p.y - at.y) * yToX);
|
|
157
171
|
return gap(segments[0]) < gap(segments.at(-1));
|
|
158
172
|
}
|
|
173
|
+
function leavesStart(edge, segments, first, stranded, yToX) {
|
|
174
|
+
return stranded ? strandSides(edge).from === "start" : nearerStart({ x: first.x0, y: first.y0 }, segments, yToX);
|
|
175
|
+
}
|
|
159
176
|
function intoDirection(last, toSegments) {
|
|
160
177
|
if (toSegments.length < 2) {
|
|
161
178
|
return void 0;
|
|
@@ -174,6 +191,8 @@ function normal(a, b) {
|
|
|
174
191
|
const len = Math.hypot(dx, dy);
|
|
175
192
|
return len > 0 ? { nx: -dy / len, ny: dx / len } : void 0;
|
|
176
193
|
}
|
|
194
|
+
var MITRE_LIMIT = 0.1;
|
|
195
|
+
var LONGEST_NORMAL = 1 / Math.sqrt(MITRE_LIMIT);
|
|
177
196
|
function pointNormalsOf(rawPoints, yToX = 1) {
|
|
178
197
|
const points = yToX === 1 ? rawPoints : rawPoints.map((p) => ({ x: p.x, y: p.y * yToX }));
|
|
179
198
|
return points.map((p, i) => {
|
|
@@ -183,16 +202,20 @@ function pointNormalsOf(rawPoints, yToX = 1) {
|
|
|
183
202
|
const nx = (before.nx + after.nx) / 2;
|
|
184
203
|
const ny = (before.ny + after.ny) / 2;
|
|
185
204
|
const dot = before.nx * nx + before.ny * ny;
|
|
186
|
-
return dot >
|
|
205
|
+
return dot > MITRE_LIMIT ? { nx: nx / dot, ny: ny / dot } : { nx, ny };
|
|
187
206
|
}
|
|
188
207
|
return before ?? after ?? { nx: 0, ny: 0 };
|
|
189
208
|
});
|
|
190
209
|
}
|
|
191
210
|
function offsetPolyline(points, normals, distance, yToX = 1) {
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
211
|
+
const out = new Array(points.length);
|
|
212
|
+
for (let i = 0; i < points.length; i++) {
|
|
213
|
+
out[i] = {
|
|
214
|
+
x: points[i].x + normals[i].nx * distance,
|
|
215
|
+
y: points[i].y + normals[i].ny * distance / yToX
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
return out;
|
|
196
219
|
}
|
|
197
220
|
function hslToRgb(h, s, l) {
|
|
198
221
|
const c = (1 - Math.abs(2 * l - 1)) * s;
|
|
@@ -393,13 +416,13 @@ function isPolylineInBounds(segments, bounds) {
|
|
|
393
416
|
}
|
|
394
417
|
return hit;
|
|
395
418
|
}
|
|
396
|
-
function isBezierInBounds(curves, bounds) {
|
|
419
|
+
function isBezierInBounds(curves, bounds, growX = 0, growY = 0) {
|
|
397
420
|
for (const c of curves) {
|
|
398
421
|
const cMinX = Math.min(c.x0, c.cx0, c.cx1, c.x1);
|
|
399
422
|
const cMaxX = Math.max(c.x0, c.cx0, c.cx1, c.x1);
|
|
400
423
|
const cMinY = Math.min(c.y0, c.cy0, c.cy1, c.y1);
|
|
401
424
|
const cMaxY = Math.max(c.y0, c.cy0, c.cy1, c.y1);
|
|
402
|
-
if (cMaxX >= bounds.minX && cMinX <= bounds.maxX && cMaxY >= bounds.minY && cMinY <= bounds.maxY) {
|
|
425
|
+
if (cMaxX >= bounds.minX - growX && cMinX <= bounds.maxX + growX && cMaxY >= bounds.minY - growY && cMinY <= bounds.maxY + growY) {
|
|
403
426
|
return true;
|
|
404
427
|
}
|
|
405
428
|
}
|
|
@@ -445,6 +468,24 @@ function pathSlotsOf(graph) {
|
|
|
445
468
|
}
|
|
446
469
|
return slots;
|
|
447
470
|
}
|
|
471
|
+
var lanesCache = weakMemo();
|
|
472
|
+
var linksCache = /* @__PURE__ */ new WeakMap();
|
|
473
|
+
function linksOf(graph) {
|
|
474
|
+
let links = linksCache.get(graph);
|
|
475
|
+
if (!links) {
|
|
476
|
+
links = /* @__PURE__ */ new Map();
|
|
477
|
+
for (const { from, to } of graph.edges) {
|
|
478
|
+
let out = links.get(from);
|
|
479
|
+
if (!out) {
|
|
480
|
+
out = /* @__PURE__ */ new Set();
|
|
481
|
+
links.set(from, out);
|
|
482
|
+
}
|
|
483
|
+
out.add(to);
|
|
484
|
+
}
|
|
485
|
+
linksCache.set(graph, links);
|
|
486
|
+
}
|
|
487
|
+
return links;
|
|
488
|
+
}
|
|
448
489
|
function buildGeometry(options) {
|
|
449
490
|
const {
|
|
450
491
|
nodePositions,
|
|
@@ -496,6 +537,94 @@ function buildGeometry(options) {
|
|
|
496
537
|
const { pathColorByIndex, pathIndexByName } = pathPaletteOf(graph);
|
|
497
538
|
const pathColorByName = (name) => pathColorByIndex[pathIndexByName.get(name) ?? -1] ?? EDGE_PATH_FALLBACK_COLOR;
|
|
498
539
|
const nodePathSlots = drawPaths && pathCount > 1 ? pathSlotsOf(graph) : NO_SLOTS;
|
|
540
|
+
const liftedWalks = highlight?.walks ?? [];
|
|
541
|
+
const threaded = threadsPasses(liftedWalks);
|
|
542
|
+
const lanePasses = liftedWalks.map((w) => w.mostPasses);
|
|
543
|
+
const thinned = threaded ? bandScale(lanePasses) : 1;
|
|
544
|
+
const fields = highlight && liftedWalks.length > 1 ? lanesCache(
|
|
545
|
+
highlight,
|
|
546
|
+
[nodePositions, version, axis.scaleX, axis.scaleY],
|
|
547
|
+
() => liftLanes(liftedWalks, nodePositions, yToX, worldPerScreenPx)
|
|
548
|
+
) : void 0;
|
|
549
|
+
const lines = fields?.lines;
|
|
550
|
+
const threads = fields?.threads;
|
|
551
|
+
const spanField = fields?.spans;
|
|
552
|
+
const plainCentres = threaded ? slotCentres(lanePasses, lanePasses) : [];
|
|
553
|
+
const centresByNode = /* @__PURE__ */ new Map();
|
|
554
|
+
const centresOf = (nodeId) => {
|
|
555
|
+
let centres = centresByNode.get(nodeId);
|
|
556
|
+
if (!centres) {
|
|
557
|
+
const spans = spanField?.get(nodeId);
|
|
558
|
+
centres = spans ? slotCentres(spans.slot, lanePasses, spans.held) : plainCentres;
|
|
559
|
+
centresByNode.set(nodeId, centres);
|
|
560
|
+
}
|
|
561
|
+
return centres;
|
|
562
|
+
};
|
|
563
|
+
const laneOffset = (nodeId, laneWidth, lane, pass) => threaded ? (centresOf(nodeId)[lane] + pass * THREAD_PITCH_PX) * thinned : (lane - (liftedWalks.length - 1) / 2) * laneWidth;
|
|
564
|
+
const laneHalfWidth = (laneWidth) => threaded ? THREAD_PX / 2 * thinned : laneWidth / 2;
|
|
565
|
+
const laneNormals = /* @__PURE__ */ new Map();
|
|
566
|
+
const laneNormalsOf = (nodeId, segments) => {
|
|
567
|
+
let normals = laneNormals.get(nodeId);
|
|
568
|
+
if (!normals) {
|
|
569
|
+
const smoothed = lines?.normals.get(nodeId);
|
|
570
|
+
normals = smoothed ? pointNormalsOf(segments, yToX).map((n, i) => smoothed[i] ?? n) : pointNormalsOf(segments, yToX);
|
|
571
|
+
laneNormals.set(nodeId, normals);
|
|
572
|
+
}
|
|
573
|
+
return normals;
|
|
574
|
+
};
|
|
575
|
+
const laneWidths = /* @__PURE__ */ new Map();
|
|
576
|
+
const laneWidthOf = (id) => {
|
|
577
|
+
let width = laneWidths.get(id);
|
|
578
|
+
if (width === void 0) {
|
|
579
|
+
const node = nodeById.get(id);
|
|
580
|
+
width = walkLaneWidthPx(
|
|
581
|
+
node ? nodeWidthPx(node, contigThickness, nodeWidth, depthNorm) : contigThickness,
|
|
582
|
+
liftedWalks.length
|
|
583
|
+
);
|
|
584
|
+
laneWidths.set(id, width);
|
|
585
|
+
}
|
|
586
|
+
return width;
|
|
587
|
+
};
|
|
588
|
+
const laneShiftOf = (nodeId, index) => lines?.shifts.get(nodeId)?.[index] ?? NO_SHIFT;
|
|
589
|
+
const laneEndOf = (id, segments, atStart) => {
|
|
590
|
+
const at = atStart ? 0 : segments.length - 1;
|
|
591
|
+
return {
|
|
592
|
+
id,
|
|
593
|
+
laneWidth: laneWidthOf(id),
|
|
594
|
+
normal: laneNormalsOf(id, segments)[at] ?? { nx: 0, ny: 0 },
|
|
595
|
+
shift: laneShiftOf(id, at)
|
|
596
|
+
};
|
|
597
|
+
};
|
|
598
|
+
const lanesMayShow = (curves, fromId) => {
|
|
599
|
+
if (!viewportBounds) {
|
|
600
|
+
return true;
|
|
601
|
+
}
|
|
602
|
+
const offset = threaded ? bandWidthPx(lanePasses) * thinned : (liftedWalks.length - 1) / 2 * laneWidthOf(fromId);
|
|
603
|
+
const reach = LONGEST_NORMAL * offset * worldPerScreenPx;
|
|
604
|
+
return isBezierInBounds(
|
|
605
|
+
curves,
|
|
606
|
+
viewportBounds,
|
|
607
|
+
reach + (fields?.furthestShift.dx ?? 0),
|
|
608
|
+
reach / yToX + (fields?.furthestShift.dy ?? 0)
|
|
609
|
+
);
|
|
610
|
+
};
|
|
611
|
+
const threadPairs = (lane, from, to) => {
|
|
612
|
+
const own = threads?.[lane]?.linkThreads;
|
|
613
|
+
if (!own?.size) {
|
|
614
|
+
return FIRST_THREADS;
|
|
615
|
+
}
|
|
616
|
+
const ahead = own.get(from)?.get(to);
|
|
617
|
+
const back = linksOf(graph).get(to)?.has(from) ? void 0 : own.get(to)?.get(from);
|
|
618
|
+
if (!back) {
|
|
619
|
+
return ahead ?? FIRST_THREADS;
|
|
620
|
+
}
|
|
621
|
+
const turned = back.map(([a, b]) => [b, a]);
|
|
622
|
+
return ahead ? [...ahead, ...turned] : turned;
|
|
623
|
+
};
|
|
624
|
+
const lanePointsOf = (nodeId, segments) => lines?.shifts.has(nodeId) ? segments.map((p, i) => {
|
|
625
|
+
const { dx, dy } = laneShiftOf(nodeId, i);
|
|
626
|
+
return { ...p, x: p.x + dx, y: p.y + dy };
|
|
627
|
+
}) : segments;
|
|
499
628
|
const showArrows = scale > (linearLayout ? 1 : MIN_ARROW_SCALE);
|
|
500
629
|
for (let ei = 0; ei < graph.edges.length; ei++) {
|
|
501
630
|
const edge = graph.edges[ei];
|
|
@@ -516,18 +645,47 @@ function buildGeometry(options) {
|
|
|
516
645
|
const toNode = nodeById.get(edge.to);
|
|
517
646
|
const intoHalfWidth = (toNode ? nodeWidthPx(toNode, contigThickness, nodeWidth, depthNorm) : contigThickness) / 2;
|
|
518
647
|
const inView = (curves) => !viewportBounds || isBezierInBounds(curves, viewportBounds);
|
|
648
|
+
const dashesOf = (curves) => dashSpans(curves, DELETION_DASH_PX / scale, yToX, viewportBounds);
|
|
519
649
|
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 });
|
|
528
|
-
}
|
|
529
|
-
} else {
|
|
650
|
+
if (!isDeletion) {
|
|
530
651
|
edgeCurves.push({ curves, thickness, color });
|
|
652
|
+
return;
|
|
653
|
+
}
|
|
654
|
+
for (const dash of dashesOf(curves)) {
|
|
655
|
+
edgeCurves.push({ curves: dash.curves, thickness, color });
|
|
656
|
+
}
|
|
657
|
+
};
|
|
658
|
+
const laneStroke = (curves, thickness, color, walk, pass, normal2, offsetX, endNormal, endOffsetX) => {
|
|
659
|
+
if (!isDeletion) {
|
|
660
|
+
edgeCurves.push({
|
|
661
|
+
curves,
|
|
662
|
+
thickness,
|
|
663
|
+
color,
|
|
664
|
+
walk,
|
|
665
|
+
pass,
|
|
666
|
+
normal: normal2,
|
|
667
|
+
offsetX,
|
|
668
|
+
endNormal,
|
|
669
|
+
endOffsetX
|
|
670
|
+
});
|
|
671
|
+
return;
|
|
672
|
+
}
|
|
673
|
+
const start = { normal: normal2, offsetX };
|
|
674
|
+
const end = { normal: endNormal, offsetX: endOffsetX };
|
|
675
|
+
for (const dash of dashesOf(curves)) {
|
|
676
|
+
const a = dash.startAlong === 0 ? start : laneSlideAt(start, end, dash.startAlong);
|
|
677
|
+
const b = dash.endAlong === 1 ? end : laneSlideAt(start, end, dash.endAlong);
|
|
678
|
+
edgeCurves.push({
|
|
679
|
+
curves: dash.curves,
|
|
680
|
+
thickness,
|
|
681
|
+
color,
|
|
682
|
+
walk,
|
|
683
|
+
pass,
|
|
684
|
+
normal: a.normal,
|
|
685
|
+
offsetX: a.offsetX,
|
|
686
|
+
endNormal: b.normal,
|
|
687
|
+
endOffsetX: b.offsetX
|
|
688
|
+
});
|
|
531
689
|
}
|
|
532
690
|
};
|
|
533
691
|
const arrowOn = (curves) => {
|
|
@@ -548,35 +706,57 @@ function buildGeometry(options) {
|
|
|
548
706
|
const edgeCurveStart = edgeCurves.length;
|
|
549
707
|
const arrowStart = arrows.length;
|
|
550
708
|
const laneWalks = highlight?.walks.length && onWalk && !ribbons ? highlight.walks : void 0;
|
|
709
|
+
if (laneWalks && !lanesMayShow(baseCurves, edge.from)) {
|
|
710
|
+
continue;
|
|
711
|
+
}
|
|
551
712
|
if (laneWalks) {
|
|
552
|
-
const
|
|
553
|
-
|
|
554
|
-
const laneWidth = walkLaneWidthPx(width, laneWalks.length);
|
|
555
|
-
const normals = pointNormalsOf(fromSegments, yToX);
|
|
556
|
-
const { nx, ny } = (leavesStart(
|
|
557
|
-
edge,
|
|
713
|
+
const from = laneEndOf(
|
|
714
|
+
edge.from,
|
|
558
715
|
fromSegments,
|
|
559
|
-
baseCurves[0],
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
716
|
+
leavesStart(edge, fromSegments, baseCurves[0], stranded, yToX)
|
|
717
|
+
);
|
|
718
|
+
const last = baseCurves.at(-1);
|
|
719
|
+
const to = threaded ? laneEndOf(
|
|
720
|
+
edge.to,
|
|
721
|
+
toSegments,
|
|
722
|
+
nearerStart({ x: last.x1, y: last.y1 }, toSegments, yToX)
|
|
723
|
+
) : from;
|
|
724
|
+
const single = laneWalks.length === 1;
|
|
725
|
+
const thickness = laneHalfWidth(from.laneWidth);
|
|
726
|
+
for (let lane = 0; lane < laneWalks.length; lane++) {
|
|
727
|
+
const walk = laneWalks[lane];
|
|
567
728
|
if (!walk.edgeIndexes.has(ei)) {
|
|
568
|
-
|
|
729
|
+
continue;
|
|
569
730
|
}
|
|
570
|
-
const
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
731
|
+
for (const [pass, toPass] of threadPairs(lane, edge.from, edge.to)) {
|
|
732
|
+
const offsetX = single ? 0 : laneOffset(from.id, from.laneWidth, lane, pass) * worldPerScreenPx;
|
|
733
|
+
const endOffsetX = threaded ? laneOffset(to.id, to.laneWidth, lane, toPass) * worldPerScreenPx : offsetX;
|
|
734
|
+
const curves = threaded ? slideCurves(
|
|
735
|
+
baseCurves,
|
|
736
|
+
from.shift.dx + from.normal.nx * offsetX,
|
|
737
|
+
from.shift.dy + from.normal.ny * offsetX / yToX,
|
|
738
|
+
to.shift.dx + to.normal.nx * endOffsetX,
|
|
739
|
+
to.shift.dy + to.normal.ny * endOffsetX / yToX
|
|
740
|
+
) : offsetX === 0 ? baseCurves : translateCurves(
|
|
741
|
+
baseCurves,
|
|
742
|
+
from.normal.nx * offsetX,
|
|
743
|
+
from.normal.ny * offsetX / yToX
|
|
577
744
|
);
|
|
745
|
+
if (inView(curves)) {
|
|
746
|
+
laneStroke(
|
|
747
|
+
curves,
|
|
748
|
+
thickness,
|
|
749
|
+
walk.colors.get(edge.from) ?? walk.colors.get(edge.to) ?? plainEdgeColor,
|
|
750
|
+
lane,
|
|
751
|
+
pass,
|
|
752
|
+
from.normal,
|
|
753
|
+
offsetX,
|
|
754
|
+
to.normal,
|
|
755
|
+
endOffsetX
|
|
756
|
+
);
|
|
757
|
+
}
|
|
578
758
|
}
|
|
579
|
-
}
|
|
759
|
+
}
|
|
580
760
|
if (edgeCurves.length > edgeCurveStart) {
|
|
581
761
|
arrowOn(baseCurves);
|
|
582
762
|
}
|
|
@@ -644,19 +824,38 @@ function buildGeometry(options) {
|
|
|
644
824
|
const lanes = highlight?.walks.length && !faded && !slots?.length ? highlight.walks : void 0;
|
|
645
825
|
if (drawable && lanes) {
|
|
646
826
|
const laneWidth = walkLaneWidthPx(width, lanes.length);
|
|
647
|
-
const normals =
|
|
648
|
-
lanes.
|
|
649
|
-
|
|
827
|
+
const normals = lanes.length > 1 ? laneNormalsOf(nodeId, segments) : [];
|
|
828
|
+
const points = lanes.length > 1 ? lanePointsOf(nodeId, segments) : segments;
|
|
829
|
+
const thickness = laneHalfWidth(laneWidth);
|
|
830
|
+
for (let lane = 0; lane < lanes.length; lane++) {
|
|
831
|
+
const laneColor = lanes[lane].colors.get(nodeId);
|
|
650
832
|
if (laneColor === void 0) {
|
|
651
|
-
|
|
833
|
+
continue;
|
|
652
834
|
}
|
|
653
|
-
const
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
835
|
+
const onThreads = threads?.[lane]?.nodeThreads.get(nodeId) ?? ONE_PASS;
|
|
836
|
+
for (const pass of onThreads) {
|
|
837
|
+
if (lanes.length === 1) {
|
|
838
|
+
nodeStrokes.push({
|
|
839
|
+
points: segments,
|
|
840
|
+
thickness,
|
|
841
|
+
color: laneColor,
|
|
842
|
+
walk: lane,
|
|
843
|
+
pass
|
|
844
|
+
});
|
|
845
|
+
continue;
|
|
846
|
+
}
|
|
847
|
+
const offsetX = laneOffset(nodeId, laneWidth, lane, pass) * worldPerScreenPx;
|
|
848
|
+
nodeStrokes.push({
|
|
849
|
+
points: offsetPolyline(points, normals, offsetX, yToX),
|
|
850
|
+
thickness,
|
|
851
|
+
color: laneColor,
|
|
852
|
+
walk: lane,
|
|
853
|
+
pass,
|
|
854
|
+
normals,
|
|
855
|
+
offsetX
|
|
856
|
+
});
|
|
857
|
+
}
|
|
858
|
+
}
|
|
660
859
|
} else if (drawable && slots?.length && slotWidth >= MIN_PATH_STRIPE_PX) {
|
|
661
860
|
const normals = pointNormalsOf(segments, yToX);
|
|
662
861
|
for (const slot of slots) {
|
|
@@ -6,10 +6,10 @@ import {
|
|
|
6
6
|
} from "./chunk-MYDHU2UV.js";
|
|
7
7
|
import {
|
|
8
8
|
readColor
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-KKHXMJEE.js";
|
|
10
10
|
import {
|
|
11
11
|
referenceWalkName
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-LODKC7PJ.js";
|
|
13
13
|
import {
|
|
14
14
|
pathOrigin
|
|
15
15
|
} from "./chunk-3YBP46PB.js";
|
|
@@ -4,27 +4,27 @@ import {
|
|
|
4
4
|
import {
|
|
5
5
|
facetLifts,
|
|
6
6
|
walkLift
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-ZWBQ4RRK.js";
|
|
8
8
|
import {
|
|
9
9
|
buildGeometry,
|
|
10
10
|
computeReferenceRamp
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-GDZQFELP.js";
|
|
12
12
|
import {
|
|
13
13
|
walkKey
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-IZKM4NY7.js";
|
|
15
15
|
import {
|
|
16
16
|
walkRowsExtent
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-VCUOYVLC.js";
|
|
18
18
|
import {
|
|
19
19
|
pathLegend,
|
|
20
20
|
walkLabelsOf
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-VQ353UDK.js";
|
|
22
22
|
import {
|
|
23
23
|
FIGURE_DEFAULTS
|
|
24
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-2MXFG3W7.js";
|
|
25
25
|
import {
|
|
26
26
|
drawingBounds
|
|
27
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-JVT3XTKN.js";
|
|
28
28
|
import {
|
|
29
29
|
referenceLabel
|
|
30
30
|
} from "./chunk-5ORP7EFJ.js";
|
|
@@ -34,7 +34,7 @@ import {
|
|
|
34
34
|
import {
|
|
35
35
|
deletionDrawing,
|
|
36
36
|
deletionEdges
|
|
37
|
-
} from "./chunk-
|
|
37
|
+
} from "./chunk-3GORESBG.js";
|
|
38
38
|
import {
|
|
39
39
|
facetCells,
|
|
40
40
|
facetSettingOf
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
coversGraph
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-SZYFZNCO.js";
|
|
4
4
|
import {
|
|
5
5
|
bubblesFromGraph,
|
|
6
6
|
derivedBubble,
|
|
@@ -10,13 +10,13 @@ import {
|
|
|
10
10
|
} from "./chunk-RFG42VIO.js";
|
|
11
11
|
import {
|
|
12
12
|
bubbleSegmentIds
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-NWEVR2OQ.js";
|
|
14
14
|
import {
|
|
15
15
|
bubbleSubgraph
|
|
16
16
|
} from "./chunk-MHZTTLBU.js";
|
|
17
17
|
import {
|
|
18
18
|
strandSides
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-JJV2GT2Z.js";
|
|
20
20
|
import {
|
|
21
21
|
pushTo
|
|
22
22
|
} from "./chunk-BSOZW3FC.js";
|
|
@@ -97,7 +97,8 @@ function visibleStretches(curves, lengths, bounds, yToX) {
|
|
|
97
97
|
});
|
|
98
98
|
return stretches;
|
|
99
99
|
}
|
|
100
|
-
|
|
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,57 @@ 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
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
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(
|
|
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, fromDx, fromDy, toDx, toDy) {
|
|
154
|
+
const n = curves.length;
|
|
155
|
+
const out = new Array(n);
|
|
156
|
+
for (let i = 0; i < n; i++) {
|
|
157
|
+
const c = curves[i];
|
|
158
|
+
const a = i / n;
|
|
159
|
+
const b = (i + 1) / n;
|
|
160
|
+
const adx = fromDx + (toDx - fromDx) * a;
|
|
161
|
+
const ady = fromDy + (toDy - fromDy) * a;
|
|
162
|
+
const bdx = fromDx + (toDx - fromDx) * b;
|
|
163
|
+
const bdy = fromDy + (toDy - fromDy) * b;
|
|
164
|
+
out[i] = {
|
|
165
|
+
x0: c.x0 + adx,
|
|
166
|
+
y0: c.y0 + ady,
|
|
167
|
+
cx0: c.cx0 + adx,
|
|
168
|
+
cy0: c.cy0 + ady,
|
|
169
|
+
cx1: c.cx1 + bdx,
|
|
170
|
+
cy1: c.cy1 + bdy,
|
|
171
|
+
x1: c.x1 + bdx,
|
|
172
|
+
y1: c.y1 + bdy
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
return out;
|
|
176
|
+
}
|
|
146
177
|
function translateCurves(curves, dx, dy) {
|
|
147
178
|
const out = new Array(curves.length);
|
|
148
179
|
for (let i = 0; i < curves.length; i++) {
|
|
@@ -555,6 +586,9 @@ export {
|
|
|
555
586
|
curveMidpoint,
|
|
556
587
|
curveBounds,
|
|
557
588
|
dashCurves,
|
|
589
|
+
dashSpans,
|
|
590
|
+
slideAt,
|
|
591
|
+
slideCurves,
|
|
558
592
|
translateCurves,
|
|
559
593
|
ownStrand,
|
|
560
594
|
strandSides,
|
|
@@ -3,14 +3,14 @@ import {
|
|
|
3
3
|
boxesGenes,
|
|
4
4
|
rowPitch,
|
|
5
5
|
rowSpan
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-IXLT3JJX.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-
|
|
13
|
+
} from "./chunk-VCUOYVLC.js";
|
|
14
14
|
import {
|
|
15
15
|
LABEL_CHAR_PX
|
|
16
16
|
} from "./chunk-AB35TJST.js";
|