MCPcopy Index your code
hub / github.com/simstudioai/sim / calculatePositions

Function calculatePositions

apps/sim/lib/workflows/autolayout/core.ts:278–378  ·  view source on GitHub ↗
(
  layers: Map<number, GraphNode[]>,
  edges: Edge[],
  options: LayoutOptions = {}
)

Source from the content-addressed store, hash-verified

276 * Target handles are also calculated per-block to ensure precise alignment.
277 */
278export function calculatePositions(
279 layers: Map<number, GraphNode[]>,
280 edges: Edge[],
281 options: LayoutOptions = {}
282): void {
283 const horizontalSpacing = options.horizontalSpacing ?? DEFAULT_LAYOUT_OPTIONS.horizontalSpacing
284 const verticalSpacing = options.verticalSpacing ?? DEFAULT_LAYOUT_OPTIONS.verticalSpacing
285 const padding = options.padding ?? DEFAULT_LAYOUT_OPTIONS.padding
286
287 const layerNumbers = Array.from(layers.keys()).sort((a, b) => a - b)
288
289 const layerWidths = new Map<number, number>()
290 for (const layerNum of layerNumbers) {
291 const nodesInLayer = layers.get(layerNum)!
292 const maxWidth = Math.max(...nodesInLayer.map((n) => n.metrics.width))
293 layerWidths.set(layerNum, maxWidth)
294 }
295
296 const layerXPositions = new Map<number, number>()
297 let cumulativeX = padding.x
298
299 for (const layerNum of layerNumbers) {
300 layerXPositions.set(layerNum, cumulativeX)
301 cumulativeX += layerWidths.get(layerNum)! + horizontalSpacing
302 }
303
304 const allNodes = new Map<string, GraphNode>()
305 for (const nodesInLayer of layers.values()) {
306 for (const node of nodesInLayer) {
307 allNodes.set(node.id, node)
308 }
309 }
310
311 const incomingEdgesMap = new Map<string, Edge[]>()
312 for (const edge of edges) {
313 if (!incomingEdgesMap.has(edge.target)) {
314 incomingEdgesMap.set(edge.target, [])
315 }
316 incomingEdgesMap.get(edge.target)!.push(edge)
317 }
318
319 for (const layerNum of layerNumbers) {
320 const nodesInLayer = layers.get(layerNum)!
321 const xPosition = layerXPositions.get(layerNum)!
322
323 const containersInLayer = nodesInLayer.filter(isContainerBlock)
324 const nonContainersInLayer = nodesInLayer.filter((n) => !isContainerBlock(n))
325
326 if (layerNum === 0) {
327 let yOffset = padding.y
328
329 containersInLayer.sort((a, b) => b.metrics.height - a.metrics.height)
330
331 for (const node of containersInLayer) {
332 node.position = { x: xPosition, y: yOffset }
333 yOffset += node.metrics.height + verticalSpacing
334 }
335

Callers 1

layoutBlocksCoreFunction · 0.85

Calls 7

getSourceHandleYOffsetFunction · 0.85
getTargetHandleYOffsetFunction · 0.85
resolveVerticalOverlapsFunction · 0.85
isContainerBlockFunction · 0.70
getMethod · 0.65
setMethod · 0.65
pushMethod · 0.45

Tested by

no test coverage detected