Skip to content

Commit a1286c6

Browse files
committed
feat: radial tree initial layout, warm-up ticks, setting tooltips and renames
1 parent d94c710 commit a1286c6

File tree

1 file changed

+35
-2
lines changed

1 file changed

+35
-2
lines changed

src/viz/force.ts

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1392,16 +1392,43 @@ function buildGraph(root: TreeNode): void {
13921392
nodes = pruneEmptyBranches(nodes);
13931393
}
13941394
const map = new Map<TreeNode, FNode>();
1395+
const nodeSet = new Set(nodes);
1396+
1397+
// Radial tree layout for initial positions
1398+
const positions = new Map<TreeNode, { x: number; y: number }>();
1399+
const cx = width / 2 || 400;
1400+
const cy = height / 2 || 300;
1401+
1402+
function layoutRadial(node: TreeNode, x: number, y: number, angleStart: number, angleSpan: number, depth: number): void {
1403+
positions.set(node, { x, y });
1404+
const children = node.children.filter((c) => nodeSet.has(c));
1405+
if (children.length === 0) return;
1406+
const radius = springLen * (depth === 0 ? 1.5 : 1);
1407+
let offset = angleStart;
1408+
const totalLeaves = children.reduce((s, c) => s + Math.max(1, c.leafCount), 0);
1409+
for (const child of children) {
1410+
const share = (Math.max(1, child.leafCount) / totalLeaves) * angleSpan;
1411+
const angle = offset + share / 2;
1412+
layoutRadial(child, x + Math.cos(angle) * radius, y + Math.sin(angle) * radius, offset, share, depth + 1);
1413+
offset += share;
1414+
}
1415+
}
1416+
1417+
const rootNode = nodes.find((n) => n.kind === "root");
1418+
if (rootNode) {
1419+
layoutRadial(rootNode, cx, cy, 0, Math.PI * 2, 0);
1420+
}
13951421

13961422
fnodes = nodes.map((n) => {
13971423
const r = n.kind === "root" ? 10 : n.kind === "area" ? 8
13981424
: (n.kind === "domain" || n.kind === "device") ? 6 : entityDotSize;
13991425
let hash = 0;
14001426
for (let i = 0; i < n.id.length; i++) hash = ((hash << 5) - hash + n.id.charCodeAt(i)) | 0;
1427+
const pos = positions.get(n);
14011428
const fn: FNode = {
14021429
tree: n,
1403-
x: Math.random() * 600 + 100,
1404-
y: Math.random() * 400 + 100,
1430+
x: pos ? pos.x : cx + (Math.random() - 0.5) * 100,
1431+
y: pos ? pos.y : cy + (Math.random() - 0.5) * 100,
14051432
vx: 0, vy: 0,
14061433
fx: null, fy: null,
14071434
r,
@@ -1435,6 +1462,12 @@ function buildGraph(root: TreeNode): void {
14351462

14361463
glowTimestamps = new Map();
14371464
rebuildClusters();
1465+
1466+
// Warm up: run simulation ticks before first render so the layout is mostly settled
1467+
for (let i = 0; i < 150; i++) {
1468+
simulate();
1469+
alpha *= alphaDecay;
1470+
}
14381471
}
14391472

14401473
function resize(): void {

0 commit comments

Comments
 (0)