A treemap divides a rectangle into sub-rectangles whose areas are proportional to a weight wi. A naive "slice-and-dice" layout just lines items up by width in a single row, which produces very thin slivers once values vary a lot. The squarified algorithm (Bruls, Huizing & van Wijk, 1999) instead builds rows greedily, adding items to the current row only while doing so keeps rectangles closer to square:
worst(row, side) = max( side²·max(row)/sum(row)²,
sum(row)²/(side²·min(row)) )
while data remains:
try adding next item to current row
if worst(row+item) >= worst(row): commit row, start new one
else: keep growing the row
lay the row out along the shorter side of
the remaining free rectangle, then shrink
that rectangle by the row's thickness
Each committed row's height is exactly Σvalue / width (or width = Σvalue / height for a vertical row), which keeps every rectangle's area exactly equal to its value — the defining property of a treemap. This is the same real algorithm the 3D version of this simulator, and libraries like D3.js's d3.treemap(), run under the hood — rendered here on a flat 2D canvas so both layouts can be compared side by side on the exact same data.
- Area of each rectangle encodes its data value.
- Aspect ratio of a rectangle is max(w/h, h/w); 1.00 is a perfect square. Squarified layouts keep this low for typical data; slice-and-dice routinely produces ratios far above it once values vary.
- The improvement readout below is measured, not hardcoded: both algorithms run on the identical current dataset every time you edit it, and the average aspect ratio of each real layout is compared directly.