Skip to content

Replace hard cutoff with graduated falloff for column-count estimate#26

Merged
Malcolmnixon merged 2 commits into
mainfrom
fix/containment-column-estimate-ratio-falloff
Jul 17, 2026
Merged

Replace hard cutoff with graduated falloff for column-count estimate#26
Malcolmnixon merged 2 commits into
mainfrom
fix/containment-column-estimate-ratio-falloff

Conversation

@Malcolmnixon

Copy link
Copy Markdown
Member

This pull request improves the containment layout algorithm by replacing a hard cutoff with a graduated falloff for the column-count-based content width estimate, making the algorithm more robust to moderate variance in box sizes. This change ensures that ordinary variance (such as label-driven width differences) does not collapse multi-column layouts into a single column, and only suppresses the column estimate in truly pathological cases. The update is thoroughly documented and covered by new, detailed tests.

Containment layout algorithm improvements:

  • Replaced the hard cutoff for applying the column-count-based content width estimate with a graduated, linear falloff between two configurable size-ratio bounds (ColumnEstimateFullWeightSizeRatio = 2.0, ColumnEstimateZeroWeightSizeRatio = 6.0). This allows moderately non-uniform box sets to still benefit from multi-column packing, while only suppressing the estimate for extremely non-uniform sets. (docs/design/rendering-layout/containment-layout-algorithm.md [1] [2]; src/DemaConsulting.Rendering.Layout/ContainmentLayoutAlgorithm.cs [3] [4] [5]

  • Added ComputeSizeRatio and ComputeColumnEstimateWeight helper methods to encapsulate the new graduated weighting logic and handle degenerate cases robustly. (src/DemaConsulting.Rendering.Layout/ContainmentLayoutAlgorithm.cs src/DemaConsulting.Rendering.Layout/ContainmentLayoutAlgorithm.csL277-R375)

Testing and regression coverage:

  • Added comprehensive unit tests for the new weighting logic, including tests for boundary cases, linear interpolation, regression for the previously reported bug (where a ratio just above 2.0 collapsed the layout), and end-to-end validation that box sets just over the old cutoff still pack into multiple columns. (test/DemaConsulting.Rendering.Layout.Tests/ContainmentLayoutAlgorithmTests.cs test/DemaConsulting.Rendering.Layout.Tests/ContainmentLayoutAlgorithmTests.csR379-R513)

These changes make the layout algorithm more resilient and user-friendly, especially for real-world data where some variance in box sizes is expected.

Malcolm Nixon added 2 commits July 16, 2026 18:45
…nt estimate

ContainmentLayoutAlgorithm.ComputeContentWidth's column-count-based width
candidate was gated by MaxColumnEstimateSizeRatio = 2.0: the candidate was
skipped entirely unless widest/narrowest <= 2.0 for both width and height.
This cliff is far too strict for realistic box sets - ordinary,
differently-named identifiers routinely exceed a 2x width ratio just from
label-length variance, disabling the heuristic and collapsing a balanced
multi-column grid into one degenerate column (observed with a real 9-box
set, widths 168-351px, ratio 2.08 - barely over the cutoff - rendering as
one long column instead of packing 2-3 per row).

Since the candidate is combined via Math.Max, it can only ever widen the
final budget, never narrow it below the widest-box/area-based floor.
Given that asymmetry, replace the hard <= 2.0 cutoff with a graduated
linear falloff: full weight at or below ColumnEstimateFullWeightSizeRatio
(2.0), zero weight at or above ColumnEstimateZeroWeightSizeRatio (6.0),
interpolating linearly in between. Over-applying the estimate costs at
most some extra whitespace; under-applying it (the old cliff's failure
mode) had no bound on how degenerate the resulting single-column layout
got.

- Renamed MaxColumnEstimateSizeRatio to ColumnEstimateFullWeightSizeRatio
  and added ColumnEstimateZeroWeightSizeRatio.
- Added ComputeColumnEstimateWeight (graduated falloff) and
  ComputeSizeRatio (zero-safe ratio) helpers, both made internal
  (alongside ComputeContentWidth) for direct unit testing.
- Added regression coverage spanning the old cliff boundary (ratios just
  below/above 2.0), the new upper falloff bound (6.0), the interpolated
  midrange, and an end-to-end test reproducing the exact reported 9-box
  scenario (ratio ~2.08) now packing into multiple rows/columns instead
  of collapsing into one column.
- Updated design doc and doc comments describing the new graduated
  behavior instead of the old hard threshold.
The 12 module-name boxes in this diagram vary in width just enough
(driven by label length) that the column-count-based content-width
candidate previously fell just over the old hard 2.0 size-ratio cutoff
and was skipped entirely, collapsing the layout into a single narrow
column (332x444). With the graduated falloff fix, the candidate still
contributes substantial weight at this ratio, producing the intended
balanced multi-column grid (452x296).
@Malcolmnixon
Malcolmnixon merged commit 4f4c102 into main Jul 17, 2026
16 of 18 checks passed
@Malcolmnixon
Malcolmnixon deleted the fix/containment-column-estimate-ratio-falloff branch July 17, 2026 00:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant