Comment concevoir un algorithme pour disposer des fenêtres (redimensionnables) à l'écran pour couvrir autant d'espace que possible?

20

Je voudrais écrire un programme simple qui accepte un ensemble de fenêtres (largeur + hauteur) et la résolution d'écran et affiche une disposition de ces fenêtres à l'écran de sorte que les fenêtres prennent le plus d'espace. Il est donc possible de redimensionner une fenêtre, tout en conservant output size >= initial sizeet le rapport hauteur / largeur. Donc, pour la fenêtre i , j'aimerais que l'algorithme retourne un tuple (x,y,width,height) .

Je pense que c'est peut-être une variante du sac à dos 2D. J'ai essayé de passer en revue les résultats sur le Web, mais ils avaient pour la plupart beaucoup d'expérience (et aucune implémentation), ce qui m'a rendu difficile à suivre.

Je suis moins intéressé par l'algorithme le plus rapide possible, mais plus par quelque chose de pratique pour mes besoins spécifiques.

daniel.jackson
la source
1
Si vous redimensionnez une fenêtre, vous ne "conservez pas sa taille initiale", juste son format, je présume.
Emre
1
Vous pouvez redimensionner une fenêtre pour couvrir l'écran, quel est le problème?
2
J'appuie le commentaire de Saeed. Vous avez besoin de contraintes supplémentaires comme des tailles minimales dans le but de minimiser la somme des redimensionnements si vous souhaitez exclure des solutions triviales. Nota bene: les mathématiciens semblent appeler des problèmes carreler pavages .
Raphael
1
Peut-être est-il préférable de dire que vous souhaitez maximiser la zone de fenêtre minimale visible et minimiser la zone de fenêtre maximale visible, mais les conflits sont autorisés ou non? Veuillez modifier votre question pour la rendre exempte de bogues, penser à l'énoncé du problème actuel n'est pas facile.
2
WminwWsize(w)W

Réponses:

9

Bien que votre question ne le dise pas, je suppose que vous ne voulez pas que les fenêtres se chevauchent.

Une approche de ce problème consiste à utiliser un solveur de contraintes tel que Choco . On écrit simplement les contraintes codant votre problème, ajuste le solveur pour qu'il agisse de manière intelligente, puis laissez-le s'exécuter. Cela signifie que toute la réflexion que vous devrez faire sera consacrée à trouver un bon moyen de coder le problème, pas à concevoir un algorithme et à faire la programmation et le réglage. Voici une réponse partielle pour vous aider à démarrer.

Supposons que la taille de l'écran soit .xmax×ymax

Pour chaque fenêtre, , vous aurez un ensemble de variables et des contraintesx i , y i , h i , w iWixi,yi,hi,wi

  • xi,yi,hi,wi0
  • xi+wixmax
  • yi+hiymax
  • Peut-être aussi quelques contraintes sur la taille minimale des fenêtres, par exemple et ainsi de suite.hi100
  • Contraintes d'aspect: si le rapport d'aspect est de 3: 4, la contrainte pourrait être quelque chose comme , où est un petit terme d'erreur non nul pour permettre une non-perfection la taille des fenêtres, sinon vous imposeriez une contrainte excessive au problème.4hiϵ3wi4hi+ϵϵ

Vous devez maintenant prendre soin du chevauchement des fenêtres. Pour chaque paire de fenêtres, , où , vous générerez des contraintes comme les suivantes, qui capturent qu'aucun coin de n'apparaît dans . Pour , générer une contrainte:Wi,WjijWjWi(x,y){(xj,yj),(xj+wj,yj),(xj,yj+hj),(xj+wj,yj+hj)}

  • ¬(xixxi+wjyiyyi+hj) .

Les contraintes spécifiées jusqu'à présent ne décrivent que des fenêtres qui ne se chevauchent pas, qui ne débordent pas sur les côtés de l'écran, qui satisfont à certaines contraintes de taille minimales et qui préservent leur rapport hauteur / largeur.

Pour obtenir un bon ajustement, vous devez spécifier une métrique qui capture ce que signifie être une bonne mise en page. Une possibilité consiste à supposer que vous souhaitez conserver des fenêtres de taille à peu près égale et / ou que vous souhaitez minimiser les "espaces blancs". Je ne pense pas que cela puisse être spécifié en utilisant Choco, mais cela peut être possible avec une autre résolution de contrainte (quelqu'un d'autre pourrait être en mesure d'aider ici).

Choco permet de maximiser wrt à une fonction objective spécifiée comme une seule variable. Sur la base de cette idée, vous pouvez maximiser les éléments suivants:

  • i(hi+wi)

en écrivant une contrainte et en disant à Choco de maximiser .c o s tcost=i(hi+wi)cost

Dave Clarke
la source
Cela semble prometteur et je jouerai certainement avec Choco pour voir comment cela fonctionne et à quelle vitesse.
daniel.jackson
Mais pourquoi le dire de manière générale? Je pense que vous pouvez exprimer les contraintes comme des inégalités linéaires, ce qui signifie que ce que vous avez est un programme linéaire vanille.
Suresh
@Suresh: N'hésitez pas à élaborer. Je ne vois pas immédiatement comment.
Dave Clarke
1

J'ai commencé à écrire un prototype pour une solution de force brute, qui, espérons-le, peut être optimisée au point où elle sera pratique.

Tout d'abord, quelques définitions: Soit l'ensemble de toutes les fenêtres. Chaque fenêtre est composée de pour les coordonnées x, y et la largeur et la hauteur. Une fenêtre est initialisée avec une largeur et une hauteur minimales.Wwxw,yw,ww,hw

L'entrée de l'algorithme est l'écran, , qui a une largeur et une hauteur et une liste de fenêtres.S

Cela fonctionne à peu près ainsi:

void fit(W, S, i, n, result)
    if i == n
        if S.score() < result.score()
            result = S
        return

    w = W[i]
    foreach x, y in S.coordinates()
        set w position to (x, y)
        while S.put(w) # check that w doesn't overlap with S's other windows and add it
            fit(W, S, i+1, n, result)
            S.windows.pop()
            w.grow()
        w.restoresize()

Il y a quelques choses qui devraient être améliorées:

  • S.coordinates()est très lent en ce moment. Il itère tous les points S.width x S.heightet vérifie si chacun se trouve dans l'une des fenêtres de S.

  • S.put()vérifie si son paramètre chevauche le reste des fenêtres de S en effectuant le test mentionné dans la réponse de Dave. Peut-être que cela peut être amélioré en utilisant des arbres d'intervalle ?

  • S.score()renvoie actuellement qui est simplement l'aire de toutes les fenêtres. Il doit prendre en compte d'autres variables pour produire de meilleures dispositions.wS.windows(hwww)

  • La fonction ci-dessus doit essayer toutes les permutations de pour obtenir le meilleur résultat possible.W

J'essaie actuellement de trouver une structure de données appropriée pour représenter l'écran et ses fenêtres, il doit prendre en charge ces requêtes:

  • renvoie une liste de coordonnées où une fenêtre donnée peut être positionnée sans se chevaucher avec d'autres
  • insérer la fenêtre à la position x, y (déjà vérifié qu'elle ne se chevauche pas)
  • retourner toutes les fenêtres
daniel.jackson
la source