开发者

Arrangement of n objects in a n x n square

if have multi开发者_运维问答ples object, how to arrange it so that each number of object in row x column will form a near square?

exp:14 objects arrange to something like this:

0 0 0 0
0 0 0 0
0 0 0 0
0 0


Take the ceil of the square root?

in python:

import math
ceil(14**(.5))

Which returns:

>>> from math import ceil
>>> ceil(14**(.5))
4.0


Get the square root of the number of items:

n = 14 ^ 0.5 ~ 3.7417

Round up to the nearest integer:

n = ceil(14 ^ 0.5) = 4

Now simply arrange the items in rows of n items until you run out.


Given n objects, the size of the resulting "square" is ceil(sqrt(n)), with special shortcut cases for n = 0 (don't draw anything) or n = 1 (just a 1x1 square).

Also, the question title is a little misleading. You can never arrange N objects in an NxN square, unless N is 1.


That depends. Assuming that the number of columns should be equal to or greater than the number of rows then the following calculates the number of columns (in pseudo-code):

Ceiling(Sqrt(n))

where n is the number of items.


If you wish to center the grid, you'll have to know how much rows you'll have ahead of time, this function (it's javascript but I think it should easily be ported to another language) will generate a grid of positions and supports centering and spacing.

In pseudo-code

columns = Ceiling(Sqrt(n))
rows    = (columns - 1) if (Round(Sqrt(n)) < columns) else columns

If center is false, the function will generate something like this (o is the origin):

+———————+
|oxx    |
|xxx    |
|xx     |
|       |
|       |
+———————+

If center is true

+———————+
|       |
|  xxx  |
|  xox  |
|   x   |
|       |
+———————+

Code

/**
 * Creates a grid of positions for the given items count and size.
 * It assumes items anchor are centered.
 *
 * @param {number}  x             - The grid x position
 * @param {number}  y             - The grid y position
 * @param {number}  count         - The number of positions you wish to create
 * @param {number}  size          - The item size
 * @param {boolean} [center=true] - If true wil center the grid according to `x`, `y`
 * @param {number}  [spacing=0]   - Item spacing
 * @return {Array.<{x: number, y: number}>} The generated positions
 */
export const makeGrid = (x, y, count, size, { center = true, spacing = 0 } = {}) => {
    // avoid computing trivial cases
    if (count === 0) return []
    if (count === 1) return [{ x, y }]

    const sqrt           = Math.sqrt(count)
    const columns        = Math.ceil(sqrt)
    const rows           = Math.round(sqrt) < columns ? columns - 1 : columns
    const sizeAndSpacing = size + spacing

    let offsetX = x
    let offsetY = y

    // if grid is centered apply offset according to `columns` and `rows`
    if (center === true) {
        offsetX -= (columns - 1) * sizeAndSpacing * .5
        offsetY -= (rows    - 1) * sizeAndSpacing * .5
    }

    let column = 0
    let row    = 0

    return _.range(count).map(() => {
        // if we're on last row's first column and grid is centered
        if (row === rows - 1 && column === 0 && center === true) {
            // if last row's items doesn't completely fill the line
            // we apply an extra offset to center them
            const modulus = count % columns
            if (modulus > 0) {
                offsetX += (columns - modulus) * sizeAndSpacing * .5
            }

        }
        const pos = {
            x: offsetX + column * sizeAndSpacing,
            y: offsetY + row    * sizeAndSpacing,
        }

        column++
        if (column === columns) {
            column = 0
            row++
        }

        return pos
    })
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜