@@ -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
14401473function resize ( ) : void {
0 commit comments