根据可用空间计算所需的列数和行数

时间:2014-01-22 15:24:52

标签: java algorithm

我需要在给定容器中分发“n”个图像。如果容器的纵横比是横向,纵向或正方形,它应该优化空间。目的是使图像尽可能大,并且所有图像都具有相同的可用空间。为此,我计划创建一个网格,但我需要知道根据容器的纵横比,它必须有多少列和多少行。

我看了this question,但这并不是我需要的。

n = 8的图像应该澄清一下:

Calculate columns and rows

如果容器是垂直的,那么需要4行和2列,如果容器是正方形,则需要3行3列,如果容器是水平的,那么2行4列是需要的。

我正在写一个函数,但我陷入了中间:

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};}

我真的很感激这里的一些帮助。

提前致谢,

3 个答案:

答案 0 :(得分:2)

我找到了一个解决方案,它可能不是最好的算法,但它至少可以用于1-20个元素,这是我需要的。我没有进一步测试。如果我找到办法,我会在以后改进它。

    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;
                }
            }
        }
    }
}

答案 1 :(得分:1)

以下是JavaScript中的内容。这对你有用吗?

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)

答案 2 :(得分:0)

假设单元格是正方形,您可以简单地执行此操作(伪代码):

float proportion = width / height;
int columns = min(cellCount, (int)round(sqrt(proportion * cellCount)));
int rows = (cellCount + columns - 1) / columns;  // int division with rounding up