namespace StellaOps.ElkSharp; internal static partial class ElkNodePlacement { internal static NodePlacementGrid ResolvePlacementGrid(IReadOnlyCollection nodes) { var actualNodes = nodes .Where(node => node.Kind is not "Start" and not "End") .ToArray(); if (actualNodes.Length == 0) { return new NodePlacementGrid(160d, 80d); } var averageWidth = actualNodes.Average(node => node.Width); var averageHeight = actualNodes.Average(node => node.Height); return new NodePlacementGrid( XStep: Math.Max(64d, Math.Round(averageWidth / 8d) * 8d), YStep: Math.Max(48d, Math.Round(averageHeight / 8d) * 8d)); } internal static int ResolveOrderingIterationCount( ElkLayoutOptions options, int edgeCount, int nodeCount) { if (options.OrderingIterations is int explicitIterations) { return Math.Max(2, explicitIterations); } var baseline = Math.Max(6, Math.Max(edgeCount / 4, nodeCount / 3)); return options.Effort switch { ElkLayoutEffort.Draft => Math.Min(8, baseline), ElkLayoutEffort.Balanced => Math.Min(14, Math.Max(8, baseline)), _ => Math.Min(24, Math.Max(12, baseline + 4)), }; } internal static int ResolvePlacementIterationCount( ElkLayoutOptions options, int nodeCount, int layerCount) { if (options.PlacementIterations is int explicitIterations) { return Math.Max(1, explicitIterations); } var baseline = Math.Max(2, Math.Max(nodeCount / 8, layerCount / 2)); return options.Effort switch { ElkLayoutEffort.Draft => Math.Min(3, baseline), ElkLayoutEffort.Balanced => Math.Min(6, Math.Max(3, baseline)), _ => Math.Min(10, Math.Max(5, baseline + 2)), }; } }