@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/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
- const child_arcs = getChildArcs(pd);
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.sweep == null)
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