@euphrasiologist/lwphylo 1.2.13 → 1.2.16
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/dist/drawPhylogeny.cjs +78 -5
- package/dist/drawPhylogeny.cjs.map +1 -1
- package/dist/drawPhylogeny.esm.js +78 -5
- package/dist/drawPhylogeny.esm.js.map +1 -1
- package/dist/drawPhylogeny.umd.js +1 -1
- package/dist/drawPhylogeny.umd.js.map +1 -1
- package/dist/index.cjs +79 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +79 -6
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -561,6 +561,54 @@ function getChildArcs(pd) {
|
|
|
561
561
|
return arcs;
|
|
562
562
|
}
|
|
563
563
|
|
|
564
|
+
function getChildArcsFan(pd) {
|
|
565
|
+
const TAU = Math.PI * 2;
|
|
566
|
+
const norm = (t) => ((t % TAU) + TAU) % TAU;
|
|
567
|
+
|
|
568
|
+
// Circular midpoint that travels CCW from a -> b by half the CCW span
|
|
569
|
+
function midCCW(a, b) {
|
|
570
|
+
const d = (b - a + TAU) % TAU; // CCW delta a->b in [0, 2π)
|
|
571
|
+
return norm(a + d / 2);
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
const byId = new Map(pd.map(d => [d.thisId, d]));
|
|
575
|
+
const childrenByParent = new Map(pd.map(d => [d.thisId, d.children || []]));
|
|
576
|
+
|
|
577
|
+
const child_arcs = [];
|
|
578
|
+
|
|
579
|
+
for (const parent of pd) {
|
|
580
|
+
const kids = childrenByParent.get(parent.thisId) || [];
|
|
581
|
+
if (kids.length < 2) continue;
|
|
582
|
+
|
|
583
|
+
// Sort children by angle (normalized) around the circle
|
|
584
|
+
const A = kids
|
|
585
|
+
.map(id => ({ id, a: norm(byId.get(id).angle) }))
|
|
586
|
+
.sort((u, v) => u.a - v.a);
|
|
587
|
+
|
|
588
|
+
const N = A.length;
|
|
589
|
+
for (let i = 0; i < N; i++) {
|
|
590
|
+
const prev = A[(i - 1 + N) % N];
|
|
591
|
+
const cur = A[i];
|
|
592
|
+
const next = A[(i + 1) % N];
|
|
593
|
+
|
|
594
|
+
// “fan” wedge around the child: midpoint(prev→cur) .. midpoint(cur→next)
|
|
595
|
+
const start = midCCW(prev.a, cur.a);
|
|
596
|
+
const end = midCCW(cur.a, next.a);
|
|
597
|
+
|
|
598
|
+
child_arcs.push({
|
|
599
|
+
parentId: parent.thisId,
|
|
600
|
+
childId: cur.id,
|
|
601
|
+
radius: parent.r, // IMPORTANT: draw at the PARENT circle
|
|
602
|
+
start,
|
|
603
|
+
end,
|
|
604
|
+
sweep: 0 // CCW (matches describeArcSweep usage)
|
|
605
|
+
});
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
return child_arcs;
|
|
610
|
+
}
|
|
611
|
+
|
|
564
612
|
// src/radial/radialLayout.js
|
|
565
613
|
|
|
566
614
|
/**
|
|
@@ -607,7 +655,12 @@ function radialLayout(node, opts = {}) {
|
|
|
607
655
|
: getArcs(pd);
|
|
608
656
|
|
|
609
657
|
// per-child arcs for half-arc highlighting if you already use them
|
|
610
|
-
|
|
658
|
+
let child_arcs = [];
|
|
659
|
+
if (opts.arcsStyle === "fan") {
|
|
660
|
+
child_arcs = getChildArcsFan(pd);
|
|
661
|
+
} else {
|
|
662
|
+
child_arcs = getChildArcs(pd);
|
|
663
|
+
}
|
|
611
664
|
|
|
612
665
|
return { data: pd, radii, arcs, child_arcs };
|
|
613
666
|
}
|
|
@@ -1329,6 +1382,29 @@ function drawPhylogeny(
|
|
|
1329
1382
|
return { X0, Y0, X1s: X0 + dx * t, Y1s: Y0 + dy * t, len };
|
|
1330
1383
|
}
|
|
1331
1384
|
|
|
1385
|
+
// put this next to your other radial helpers (top of file or in your lib)
|
|
1386
|
+
function arcPathCCW(cx, cy, R, a0, a1) {
|
|
1387
|
+
const TAU = Math.PI * 2;
|
|
1388
|
+
const norm = (t) => ((t % TAU) + TAU) % TAU;
|
|
1389
|
+
|
|
1390
|
+
a0 = norm(a0);
|
|
1391
|
+
a1 = norm(a1);
|
|
1392
|
+
|
|
1393
|
+
const delta = (a1 - a0 + TAU) % TAU; // CCW span a0 -> a1 in [0, 2π)
|
|
1394
|
+
if (delta < 1e-9) return ""; // degenerate; draw nothing
|
|
1395
|
+
|
|
1396
|
+
// With your polarToCartesian using y = cy - r*sin(t),
|
|
1397
|
+
// sweepFlag=0 gives a visually CCW arc segment.
|
|
1398
|
+
const largeArcFlag = delta > Math.PI ? 1 : 0;
|
|
1399
|
+
const sweepFlag = 0;
|
|
1400
|
+
|
|
1401
|
+
const p0 = polarToCartesian(cx, cy, R, a0);
|
|
1402
|
+
const p1 = polarToCartesian(cx, cy, R, a1);
|
|
1403
|
+
|
|
1404
|
+
return `M ${p0.x} ${p0.y} A ${R} ${R} 0 ${largeArcFlag} ${sweepFlag} ${p1.x} ${p1.y}`;
|
|
1405
|
+
}
|
|
1406
|
+
|
|
1407
|
+
|
|
1332
1408
|
// ===== SVG ROOT =====
|
|
1333
1409
|
const svg = d3
|
|
1334
1410
|
.create("svg")
|
|
@@ -1370,7 +1446,6 @@ function drawPhylogeny(
|
|
|
1370
1446
|
d.sweep
|
|
1371
1447
|
)
|
|
1372
1448
|
)
|
|
1373
|
-
|
|
1374
1449
|
.attr("fill", "none")
|
|
1375
1450
|
.attr("stroke", "#777")
|
|
1376
1451
|
.attr("stroke-width", strokeWidth);
|
|
@@ -1549,9 +1624,7 @@ function drawPhylogeny(
|
|
|
1549
1624
|
// ----- half-arc at parent radius (parent.angle → child.angle) -----
|
|
1550
1625
|
const a = arcByChild.get(cur.thisId);
|
|
1551
1626
|
if (a) {
|
|
1552
|
-
const pathD = (a.
|
|
1553
|
-
? describeArc(centerX, centerY, radiusPx(a.radius), a.start, a.end)
|
|
1554
|
-
: describeArcSweep(centerX, centerY, radiusPx(a.radius), a.start, a.end, a.sweep);
|
|
1627
|
+
const pathD = arcPathCCW(centerX, centerY, radiusPx(a.radius), a.start, a.end);
|
|
1555
1628
|
|
|
1556
1629
|
arcLayer
|
|
1557
1630
|
.append("path")
|
|
@@ -1807,5 +1880,5 @@ function drawPhylogeny(
|
|
|
1807
1880
|
}
|
|
1808
1881
|
}
|
|
1809
1882
|
|
|
1810
|
-
export { describeArc, describeArcSweep, drawPhylogeny, parentFisheye, phisheye, radialLayout, readTree, rectangleLayout, subTree, unrooted };
|
|
1883
|
+
export { describeArc, describeArcSweep, drawPhylogeny, parentFisheye, phisheye, polarToCartesian, radialLayout, readTree, rectangleLayout, subTree, unrooted };
|
|
1811
1884
|
//# sourceMappingURL=index.js.map
|