54 lines
1.0 KiB
TypeScript
54 lines
1.0 KiB
TypeScript
import dagre from 'dagre'
|
|
|
|
interface NodeInfo {
|
|
id: string
|
|
label: string
|
|
}
|
|
|
|
interface EdgeInfo {
|
|
source: string
|
|
target: string
|
|
}
|
|
|
|
const NODE_W = 180
|
|
const NODE_H = 60
|
|
|
|
export function computePositions(
|
|
nodes: NodeInfo[],
|
|
edges: EdgeInfo[],
|
|
_startScene: string,
|
|
): Map<string, { x: number; y: number }> {
|
|
const g = new dagre.graphlib.Graph()
|
|
g.setGraph({
|
|
rankdir: 'LR',
|
|
nodesep: 100,
|
|
ranksep: 200,
|
|
marginx: 60,
|
|
marginy: 60,
|
|
})
|
|
g.setDefaultEdgeLabel(() => ({}))
|
|
|
|
for (const n of nodes) {
|
|
g.setNode(n.id, { width: NODE_W, height: NODE_H })
|
|
}
|
|
|
|
const nodeIds = new Set(nodes.map((n) => n.id))
|
|
for (const e of edges) {
|
|
if (nodeIds.has(e.source) && nodeIds.has(e.target)) {
|
|
g.setEdge(e.source, e.target)
|
|
}
|
|
}
|
|
|
|
dagre.layout(g)
|
|
|
|
const positions = new Map<string, { x: number; y: number }>()
|
|
for (const n of nodes) {
|
|
const node = g.node(n.id)
|
|
if (node) {
|
|
positions.set(n.id, { x: node.x - NODE_W / 2, y: node.y - NODE_H / 2 })
|
|
}
|
|
}
|
|
|
|
return positions
|
|
}
|