Pack

Pack :: # (opaque)

Placement-independent packing for disconnected components and forests.

pack : List({ width : F64, height : F64 }), Settings -> {
    positions : List({ x : F64, y : F64 }),
    bounds : { x : F64, y : F64, width : F64, height : F64 },
}

Arrange component boxes into shelves so the whole drawing approaches target_aspect with gap empty space between neighbors. Returns each box's center position, index-aligned to the input, plus tight bounds anchored at the origin.

Deterministic shelf packing: boxes are sorted by descending larger extent (the larger of width and height), ties broken by ascending input index, then placed left-to-right into shelves; a new shelf opens below the current one when the row's width would exceed the target width, derived from the total box area and target_aspect but never narrower than the widest single box. A shelf always accepts at least one box, so zero-size boxes and an empty input are legal and give defined results.

This pass is placement-independent and has no build step, so it is total instead of validating: a gap below zero behaves as 0, and a target_aspect that is not finite or not above zero behaves as 1.

row : List({ width : F64, height : F64 }), F64 -> {
    positions : List({ x : F64, y : F64 }),
    bounds : { x : F64, y : F64, width : F64, height : F64 },
}

Naive shelf packer: place component boxes in one left-to-right row.

Settings : { gap : F64, target_aspect : F64 }

Space between packed boxes and the width-to-height shape the packed drawing aims for (1.0 targets a square).