I have a variable amount of image tiles of specific dimensions that need to be fit into a grid. What is the best method of creating a grid that approximates a square the best?
For example, if the tiles were 1×2, and I had 2 tiles, then it would need to place the 2 tiles next to each other horizontally to create a square image. However, if I had 3 tiles, then it would place 2 across and 1 on the next row, to create the outline of a square grid with 1 tile missing.
This is what I tried, but there’s some issues:
tile_number = 12
thumbnail_size = (192, 272) # size of image tiles
ratio_x = thumbnail_size[1]/thumbnail_size[0]
ratio_y = thumbnail_size[0]/thumbnail_size[1]
tr_x, tr_y = tile_number*ratio_x, tile_number*ratio_y
trx_sqrt, try_sqrt = math.sqrt(tr_x), math.sqrt(tr_y)
tile_x, tile_y = round(trx_sqrt), round(try_sqrt)
if tile_x*tile_y < tile_number:
tile_y += 1
print(f'Grid: {tile_x}x{tile_y}')
If I try a grid of 3 tiles, it should give a grid of 2×2, but it gives a grid of 2×1 instead. To fix this, I just manually adjusted the number of rows by 1, if the grid size is lower than the number of images.
Also, for a grid of 9 tiles, it returns a 4×4 grid. I think its calculating that the 4×4 grid of these tiles is more square than the 3×3 grid, but I would rather have the grid be a little less square if it means its filled out better (there will be 3 free spaces in the 4×4, and no free spaces in 3×3 grid).
I thought this was going to be a simple problem, maybe it is and I’m being daft… I cant seem to figure it out though! Help would be very much appreciated. Thanks!
You’re almost there. Since you want special rules for non-perfect squares (like 3 grids giving 3 x 1, instead of 2 x 2) — Can try something like this:
def almost_square_grids(ngrids, how='square'):
nrow = ncol = int(ngrids**0.5) #floor of squareroot
which = True
while (nrow * ncol) < ngrids:
if how == 'square': #flip flop
which = not which
elif how == 'extra_rows':
which = True
elif how == 'extra_cols':
which = False
if which:
nrow += 1
else:
ncol += 1
return nrow, ncol
print(f"{'N':>3} → {'square':^8}",
f"{'extra_rows':^12}",
f"{'extra_cols':^12}", sep='|')
for ngrids in [1, 2, 3, 4, 8, 9, 10, 15, 16, 17]:
square = almost_square_grids(ngrids, how='square')
xrows = almost_square_grids(ngrids, how='extra_rows')
xcols = almost_square_grids(ngrids, how='extra_cols')
print(f"{ngrids:>3} → {repr(square):^8}",
f"{repr(xrows):^12}",
f"{repr(xcols):^12}", sep='|')
Output:
N → square | extra_rows | extra_cols
1 → (1, 1) | (1, 1) | (1, 1)
2 → (1, 2) | (2, 1) | (1, 2)
3 → (2, 2) | (3, 1) | (1, 3)
4 → (2, 2) | (2, 2) | (2, 2)
8 → (3, 3) | (4, 2) | (2, 4)
9 → (3, 3) | (3, 3) | (3, 3)
10 → (3, 4) | (4, 3) | (3, 4)
15 → (4, 4) | (5, 3) | (3, 5)
16 → (4, 4) | (4, 4) | (4, 4)
17 → (4, 5) | (5, 4) | (4, 5)
Can modify based on thumbnail ratio being more row-like or column-like.
1