Come escogitare un algoritmo per disporre le finestre (ridimensionabili) sullo schermo in modo da coprire quanto più spazio possibile?


20

Vorrei scrivere un semplice programma che accetta una serie di finestre (larghezza + altezza) e la risoluzione dello schermo e genera una disposizione di quelle finestre sullo schermo in modo che le finestre occupino più spazio. Pertanto è possibile ridimensionare una finestra, mantenendo output size >= initial sizee le proporzioni. Quindi per la finestra i , vorrei che l'algoritmo restituisse una tupla (x,y,width,height) .

Credo che questa potrebbe essere una variante dello zaino 2D. Ho provato a esaminare i risultati sul Web, ma per lo più avevano molti background (e nessuna implementazione) che mi hanno reso difficile seguirli.

Sono meno interessato all'algoritmo più veloce possibile, ma più a qualcosa di pratico per le mie esigenze specifiche.


1
Se stai ridimensionando una finestra, non stai "mantenendo le sue dimensioni iniziali", presumo solo le sue proporzioni.
Emre,

1
Puoi ridimensionare una finestra per coprire lo schermo, qual è il problema?

2
Secondo il commento di Saeed. Hai bisogno di ulteriori vincoli come dimensioni minime l'obiettivo di ridurre al minimo la somma dei ridimensionamenti se si desidera escludere soluzioni banali. Nota bene: i matematici sembrano chiamare tessellazioni di problemi di piastrellatura .
Raffaello

1
Forse è meglio dire che vuoi massimizzare l'area minima visibile della finestra e minimizzare l'area massima visibile della finestra, ma i conflitti sono permessi o no? Modifica la tua domanda per renderla libera da bug, pensare all'attuale dichiarazione del problema non è facile.

2
WminwWsize(w)W

Risposte:


9

Sebbene la tua domanda non lo dica, presumo che non desideri che le finestre si sovrappongano.

Un approccio a questo problema consiste nell'utilizzare un risolutore di vincoli come Choco . Uno semplicemente annota i vincoli che codificano il tuo problema, sintonizza il risolutore per agire in modo intelligente e quindi lascialo correre. Ciò significa che tutto il pensiero che devi fare sarà speso per trovare un buon modo per codificare il problema, non per escogitare un algoritmo e fare la programmazione e il tuning. Ecco una risposta parziale per iniziare.

Supponiamo che la dimensione dello schermo sia di .xmax×ymax

Per ogni finestra, , avrai una serie di variabili e vincolix i , y i , h i , w iWixi,yi,hi,wi

  • xi,yi,hi,wi0
  • xi+wixmax
  • yi+hiymax
  • Forse anche alcuni vincoli sulla dimensione minima di Windows, ad esempio, e così via.hi100
  • Vincoli di aspetto: se le proporzioni sono 3: 4, il vincolo potrebbe essere simile a , dove è un piccolo termine di errore diverso da zero per consentire un non perfetto dimensioni della finestra, altrimenti si vincolerebbe eccessivamente il problema.ϵ4hiϵ3wi4hi+ϵϵ

Ora devi occuparti della sovrapposizione delle finestre. Per ogni coppia di finestre, , dove , genererai vincoli come i seguenti, che catturano che nessun angolo di appare all'interno di . Per , genera il vincolo: i j W jWi,WjijWjWi(x,y){(xj,yj),(xj+wj,yj),(xj,yj+hj),(xj+wj,yj+hj)}

  • ¬(xixxi+wjyiyyi+hj) .

I vincoli specificati finora descrivono solo finestre non sovrapposte che non si estendono sui lati dello schermo, che soddisfano alcuni vincoli di dimensioni minime e ne preservano le proporzioni.

Per ottenere un buon adattamento, è necessario specificare una metrica che catturi il significato di un buon layout. Una possibilità è presumere che si desideri mantenere le finestre di dimensioni approssimativamente uguali e / o che si desideri ridurre al minimo lo "spazio bianco". Non penso che questo possa essere specificato usando Choco, ma potrebbe essere possibile risolvere un altro vincolo (qualcun altro potrebbe essere in grado di aiutare qui).

Choco consente di massimizzare wrt rispetto a una funzione obiettiva specificata come singola variabile. Sulla base di questa idea, è possibile massimizzare quanto segue:

  • i(hi+wi)

scrivendo un vincolo e dicendo a Choco di massimizzare .c o s tcost=i(hi+wi)cost


Sembra promettente e sicuramente suonerò con Choco per vedere come funziona e quanto velocemente.
daniel.jackson,

Ma perché esprimerlo così in generale? Penso che tu possa definire i vincoli come disuguaglianze lineari, il che significa che quello che hai è un programma lineare vaniglia.
Suresh,

@Suresh: sentiti libero di elaborare. Non vedo immediatamente come.
Dave Clarke,

1

Ho iniziato a scrivere un prototipo per una soluzione di forza bruta, che si spera possa essere ottimizzata al punto da renderla pratica.

Innanzitutto, alcune definizioni: Sia l'insieme di tutte le finestre. Ogni finestra è composta da per le coordinate x, y e larghezza e altezza. Una finestra viene inizializzata con una larghezza e un'altezza minime.w xWwxw,yw,ww,hw

L'input dell'algoritmo è lo schermo, , che ha una larghezza e altezza e un elenco di finestre.S

Funziona più o meno così:

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()

Ci sono alcune cose che dovrebbero essere migliorate:

  • S.coordinates()è molto lento in questo momento. Ripete tutti i punti S.width x S.heighte controlla se ognuno è in una delle finestre di S.

  • S.put()controlla se il suo parametro si sovrappone al resto delle finestre di S facendo il test menzionato nella risposta di Dave. Forse questo può essere migliorato usando gli alberi degli intervalli ?

  • S.score()attualmente restituisce che è semplicemente l'area di tutte le finestre. Deve tenere conto di altre variabili per produrre layout migliori.wS.windows(hwww)

  • La funzione sopra deve provare tutte le permutazioni di per ottenere il miglior risultato possibile.W

Attualmente sto cercando di capire una struttura dati adeguata per rappresentare lo schermo e le sue finestre, deve supportare queste query:

  • restituisce un elenco di coordinate in cui è possibile posizionare una determinata finestra senza sovrapposizioni con altre
  • inserisci la finestra in posizione x, y (già verificato che non si sovrapponga)
  • restituisce tutte le finestre
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.