Replace hard cutoff with graduated falloff for column-count estimate#26
Merged
Malcolmnixon merged 2 commits intoJul 17, 2026
Merged
Conversation
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).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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
ComputeSizeRatioandComputeColumnEstimateWeighthelper methods to encapsulate the new graduated weighting logic and handle degenerate cases robustly. (src/DemaConsulting.Rendering.Layout/ContainmentLayoutAlgorithm.cssrc/DemaConsulting.Rendering.Layout/ContainmentLayoutAlgorithm.csL277-R375)Testing and regression coverage:
test/DemaConsulting.Rendering.Layout.Tests/ContainmentLayoutAlgorithmTests.cstest/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.