7
votes

Grille optimisée pour les articles rectangulaires

J'ai n articles rectangulaires avec un rapport d'aspect AITEM (x: y).
J'ai une zone d'affichage rectangulaire avec un rapport d'aspect Aperiew

Les éléments doivent être agencés dans une mise en page similaire à une table (I.E. R lignes, Colonnes C).

Quelles sont les lignes de grille idéales x colonnes, de sorte que les articles individuels sont plus importants? (rangées * colums> = n, bien sûr - c'est-à-dire des lieux de grille "inutilisés").

Un simple algorithme pourrait itération sur des lignes = 1..n, calculer le nombre de colonnes requis et conserver la paire de lignes / colonne avec les plus grands objets.

Je me demande s'il y a un algorithme non itératif, bien que (par exemple pour AITEM = AITEM = AITEW = 1, les rangées / cols peuvent être approchées par SQRT (N)).


0 commentaires

4 Réponses :


0
votes

bonne question. Si votre vue a des dimensions A x B (fixes) et vos éléments ont des dimensions A x B (variable, à optimiser), vous avez besoin de:

Trunc (A / A) * TRUNC (B / B)> = N

Je n'ai aucune idée de la façon de résoudre cependant - la trunc est la partie délicate, car elle est non linéaire.


0 commentaires

1
votes

Votre solution peut être facilement améliorée pour gérer le boîtier générique:

Si nous [temporaires) oublient la nécessité d'avoir un nombre entier de lignes et de colonnes, nous avons

lignes * colonnes = n

x = aitem * y

AVIEW = lignes * x = lignes * aitem * y

1 = colonnes * y = (n / rangs) * (AVIEW / [lignes AITM *]) = N * AVIEW / (AITEM * ROWS²)

d'où rangées = sqrt (n * aview / aitem) et colonnes = n / rangs = sqrt (N * AITEM / AVIEW)

puis le plafond (rangées) et le plafond (colonnes) sont une solution pendant que le sol (rangées) et le plancher (colonnes) sont trop petits pour être une solution ensemble (si des rangées et des colonnes ne sont pas des entiers). Cela laisse 3 solutions possibles:

  • plancher (lignes) CEIL (colonnes)
  • plafond (lignes) au plafond (colonnes)
  • CEIL (ROUES) CEIL (Colonnes)

    édité pour corriger les équations. Le premier résultat était faux (voir Commentaires)


2 commentaires

Je pense [aitem * une vue] dans vos dernières équations est une faute de frappe. Qu'en est-il du cas où n = 2, une vue = 6, élément = 3. Vous vous retrouveriez avec trop de colonnes.


Ce n'est pas une faute de frappe. C'est une erreur dans les premières équations, où j'ai pris des définitions opposées d'APRIEW et AITEM. Il est embarrassant car ma formule initiale n'était pas homogène (oui, je suis un physicien) et l'erreur apparaît sur un cas de test simple. Merci de le pointer. Maintenant, nous avons 2 lignes et 1 colonne pour votre témoignage, comme prévu



5
votes

Remarque: Je ne pouvais pas tout à fait comprendre la réponse de Frédy Ric, alors j'ai travaillé le problème moi-même et j'ai proposé ce qui semble être la même solution. Je pensais que je pourrais aussi bien expliquer ce que j'ai fait au cas où il serait utile.

J'ai d'abord normalisé le rapport d'aspect de la vue sur celle des articles. (Je suppose que vous ne voulez pas faire pivoter les objets.) xxx

emballage maintenant un rapport rectangle de largeur / hauteur A avec des carrés équivaut à emballer la vue avec des éléments. Le cas idéal serait pour notre grille (de carrés maintenant) de remplir complètement le rectangle, ce qui nous donnerait xxx

r et C sont les nombres de lignes et de colonnes: xxx

multiplier / diviser ces deux équations nous donne xxx < p> Si la grille est parfaite, r et c sera des entiers, mais sinon, vous devez essayer les trois options d'options mentionnées et conserver la seule. où r * c est le plus petit mais reste plus que n :

  • étage (r), plafond (c)
  • plafond (r), plancher (c)
  • CEIL (R), CEIL (C)

2 commentaires

Merci pour vos commentaires détaillés. J'ai toujours des cas où la recherche de la force brute "a l'air mieux" que ces résultats de la vôtre / la suggestion de Frederics. Peut-être que je suis toujours soméhign Wrogn avec arrondir, bien que ... je joue avec ce seul temps partiel.


Une décennie plus tard, mais cette réponse m'a sauvé beaucoup de problèmes et rendait le programme dans ma tête possible. Merci beaucoup.



0
votes

Je n'ai pas pu obtenir les réponses à cette question au travail pour moi, mais j'ai trouvé une mise en œuvre soignée à une question similaire de Neptilo . Cela n'a pas fonctionné pour les rectangles, mais seulement des carrés. J'ai donc appliqué l'idée de MCkeed pour normaliser le rectangle, puis suivez l'algorithme pour les carrés.

Le résultat est le FITOCONTAINER () CODE> Fonction. Donnez-lui le nombre de rectangles à adapter n code>, le conteneurwidth code> et conteneurheight code> et l'original itemWidth code> et et Itemheight code>. Dans le cas d'éléments n'a pas de largeur et de hauteur d'origine, utilisez itemWidth code> et itemheight code> pour spécifier le rapport souhaité des éléments. P>

par exemple fittocontainer (10, 1920, 1080, 16, 9) Code> Résultats dans {NRows: 4, NCOLS: 3, itemWidth: 480, itemHeight: 270} code>, donc quatre colonnes et 3 lignes de 480 x 270 (pixels, ou quelle que soit l'unité). P>

et pour s'adapter 10 carrés dans le même exemple de la zone de 1920x1080, vous pouvez appeler FittOContainer (10, 1920, 1080, 1, 1) résultant de {NRows: 2, NCOLS: 5, itemWidth: 384, ItemHeight: 384} Code>. P>

function fitToContainer(n, containerWidth, containerHeight, itemWidth, itemHeight) {
    // We're not necessarily dealing with squares but rectangles (itemWidth x itemHeight),
    // temporarily compensate the containerWidth to handle as rectangles
    containerWidth = containerWidth * itemHeight / itemWidth;
    // Compute number of rows and columns, and cell size
    var ratio = containerWidth / containerHeight;
    var ncols_float = Math.sqrt(n * ratio);
    var nrows_float = n / ncols_float;

    // Find best option filling the whole height
    var nrows1 = Math.ceil(nrows_float);
    var ncols1 = Math.ceil(n / nrows1);
    while (nrows1 * ratio < ncols1) {
        nrows1++;
        ncols1 = Math.ceil(n / nrows1);
    }
    var cell_size1 = containerHeight / nrows1;

    // Find best option filling the whole width
    var ncols2 = Math.ceil(ncols_float);
    var nrows2 = Math.ceil(n / ncols2);
    while (ncols2 < nrows2 * ratio) {
        ncols2++;
        nrows2 = Math.ceil(n / ncols2);
    }
    var cell_size2 = containerWidth / ncols2;

    // Find the best values
    var nrows, ncols, cell_size;
    if (cell_size1 < cell_size2) {
        nrows = nrows2;
        ncols = ncols2;
        cell_size = cell_size2;
    } else {
        nrows = nrows1;
        ncols = ncols1;
        cell_size = cell_size1;
    }

    // Undo compensation on width, to make squares into desired ratio
    itemWidth = cell_size * itemWidth / itemHeight;
    itemHeight = cell_size;
    return { nrows: nrows, ncols: ncols, itemWidth: itemWidth, itemHeight: itemHeight }
}


0 commentaires