I need to distribute "n" amount of images in a given container. It should optimize the space depending if the container's aspect ratio is landscape, portrait or a square. The intention is that the images are rendered the biggest size possible and all of them have the same space available. For this, I plan to create a grid but I need to know how many columns and how many rows it must have according to the aspect ratio of the container.
I took a look at this question but it is not exactly what I need.
This image with n = 8 should clarify a bit:
If the container is vertical, then 4 rows and 2 columns are needed, if the container is a square, then 3 rows and 3 columns are needed, if the container is horizontal, then 2 rows and 4 columns are needed.
I am writing a function but I am stuck in the middle:
private int[] calculateRowsAndColumnsNeeded(int numberOfImages, Dimension containerSize){
int numberOfColumns = 0;
int numberOfRows = 0;
int containerArea = containerSize.height * containerSize.width;
float singleCellArea = containerArea / numberOfImages;
double cellSideLength = Math.sqrt(singleCellArea);
// What to do with cellSideLength to get the right number of columns and rows?
return new int[]{numberOfColumns, numberOfRows};}
I would really appreciate some help here.
Thanks in advance,
Diego
I came to a solution, it might be not the best algorithm but it works, at least, for 1 - 20 elements which is what I need. I didn't test further. I will improve it later if I find a way.
private static int[] calculateRowsAndColumnsNeeded(int numberOfImages, Dimension containerSize){
int colsAttempt = 0;
int rowsAttempt = 0;
// Calculate the length of one side from a single cell
int containerArea = containerSize.height * containerSize.width;
float singleCellArea = containerArea / numberOfImages;
double cellSideLength = Math.sqrt(singleCellArea);
colsAttempt = (int) Math.floor(containerSize.width / cellSideLength);
rowsAttempt = (int) Math.floor(containerSize.height / cellSideLength);
if (colsAttempt * rowsAttempt >= numberOfImages){
return new int[]{rowsAttempt, colsAttempt};
}
// If the container is a square or bigger horizontally than vertically
else if (containerSize.height <= containerSize.width){
colsAttempt = (int) Math.ceil(containerSize.width / cellSideLength);
rowsAttempt = (int) Math.floor(containerSize.height / cellSideLength);
if (colsAttempt * rowsAttempt >= numberOfImages){
//
return new int[]{rowsAttempt, colsAttempt};
}else{
colsAttempt = (int) Math.floor(containerSize.width / cellSideLength);
rowsAttempt = (int) Math.ceil(containerSize.height / cellSideLength);
if (colsAttempt * rowsAttempt >= numberOfImages){
return new int[]{rowsAttempt, colsAttempt};
}else{
colsAttempt = (int) Math.ceil(containerSize.width / cellSideLength);
rowsAttempt = (int) Math.ceil(containerSize.height / cellSideLength);
if (colsAttempt * rowsAttempt >= numberOfImages){
return new int[]{rowsAttempt, colsAttempt};
}else{
return null;
}
}
}
}
// If the container is bigger vertically than horizontally
else {
colsAttempt = (int) Math.floor(containerSize.width / cellSideLength);
rowsAttempt = (int) Math.ceil(containerSize.height / cellSideLength);
if (colsAttempt * rowsAttempt >= numberOfImages){
//
return new int[]{rowsAttempt, colsAttempt};
}else{
colsAttempt = (int) Math.ceil(containerSize.width / cellSideLength);
rowsAttempt = (int) Math.floor(containerSize.height / cellSideLength);
if (colsAttempt * rowsAttempt >= numberOfImages){
return new int[]{rowsAttempt, colsAttempt};
}else{
colsAttempt = (int) Math.ceil(containerSize.width / cellSideLength);
rowsAttempt = (int) Math.ceil(containerSize.height / cellSideLength);
if (colsAttempt * rowsAttempt >= numberOfImages){
return new int[]{rowsAttempt, colsAttempt};
}else{
return null;
}
}
}
}
}
Here's something in JavaScript. Does this work for you?
var height = 30, //pixels
width = 30, //pixels
n = 8,
cellSideLength = Math.floor(Math.sqrt(height * width / n)),
targetColumns = Math.floor(width / cellSideLength) == width / cellSideLength
? width/cellSideLength
: Math.floor(width / cellSideLength) + 1,
cellSideLengthTemp = cellSideLength
targetColumns = Math.min(targetColumns,n)
while (width / cellSideLengthTemp < targetColumns)
cellSideLengthTemp-- //decrease by one pixel
while (Math.floor(height / cellSideLengthTemp) * targetColumns < n)
cellSideLengthTemp-- //decrease by one pixel
var numColumns = Math.floor(width / cellSideLengthTemp),
numRows = 1
while (numColumns * numRows < n)
numRows++
console.log(numColumns,numRows,cellSideLengthTemp,cellSideLength)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With