Ekrandaki pencereleri mümkün olduğunca çok yer kaplayacak şekilde düzenlemek (yeniden boyutlandırılabilir) için bir algoritma nasıl tasarlanır?


20

Bir dizi pencere (genişlik + yükseklik) ve ekran çözünürlüğünü kabul eden ve pencerelerin en fazla yer kaplayacak şekilde ekranda bu pencerelerin bir düzenlemesini çıkaran basit bir program yazmak istiyorum. Bu nedenle, output size >= initial sizeve en boy oranını koruyarak bir pencereyi yeniden boyutlandırmak mümkündür . Pencere , algoritmanın bir demet döndürmesini istiyorum .( x , y , w i d t h , h e i g h t )ben(x,y,width,height)

Bunun 2D Knapsack'in bir varyasyonu olabileceğine inanıyorum. Web etrafında sonuçları üzerinden gitmeye çalıştım ama çoğunlukla takip için zorlaştırdı arka plan (ve hiçbir uygulama) bir sürü vardı.

Mümkün olan en hızlı algoritmaya daha az ilgi duyuyorum, ancak daha çok özel ihtiyacım için pratik olan bir şeyle ilgileniyorum.


1
Bir pencereyi yeniden boyutlandırıyorsanız, "başlangıç ​​boyutunu koruyor" değil, sadece en boy oranına sahip olduğunuzu düşünüyorum.
Emre

1
Bir pencereyi ekranı kaplayacak şekilde yeniden boyutlandırabilirsiniz, sorun nedir?

2
Saeed'in ikinci yorumu. Önemsiz çözümleri hariç tutmak istiyorsanız, yeniden boyutlandırmaların toplamını en aza indirme hedefi gibi minimum boyutlar gibi ek kısıtlamalara ihtiyacınız vardır. Not: matematikçiler döşeme problemleri mozaikleme olarak adlandırılıyor gibi görünüyor .
Raphael

1
Görüntülenebilir minimum pencere alanını en üst düzeye çıkarmak ve görüntülenebilir maksimum pencere alanını en aza indirmek istediğinizi söylemek daha iyi olabilir, ancak çakışmalara izin veriliyor veya verilmiyor mu? Sorunuzu hatasız hale getirmek için lütfen düzenleyin, mevcut sorun bildirimini düşünmek kolay değildir.

2
WminwWsize(w)W

Yanıtlar:


9

Sorunuz bunu söylemese de, pencerelerin çakışmasını istemediğinizi varsayıyorum.

Bu soruna bir yaklaşım Choco gibi bir kısıtlama çözücüsü kullanmaktır . Biri, probleminizi kodlayan kısıtlamaları yazar, çözücüyü akıllı bir şekilde harekete geçirir ve sonra çalışmasına izin verir. Bu, yapmanız gereken tüm düşüncenin, problemi kodlamanın iyi bir yolunu bulmak için harcanacağı anlamına gelir, bir algoritma tasarlamak ve programlama ve ayarlama yapmak değil. İşte başlamanız için kısmi bir cevap.

Ekran boyutunun .xmax×ymax

Her pencere için, , bir dizi değişkeniniz olacak ve kısıtlamalarx i , y i , h i , w iWixi,yi,hi,wi

  • xi,yi,hi,wi0
  • xi+wixmax
  • yi+hiymax
  • Belki de pencerelerin minimum boyutuyla ilgili bazı kısıtlamalar, örneğin, vb.hben100
  • En boy oranı kısıtlamaları: En boy oranı 3: 4 ise, kısıtlama gibi bir şey olabilir , burada ϵ mükemmel olmayan pencereye izin vermek için sıfır olmayan bir hata terimidir boyutları, aksi takdirde sorunu aşırı kısıtlarsınız.4hben-ε3wben4hben+εε

Şimdi pencere örtüşmesine dikkat etmeniz gerekiyor. Pencerelerin Her çift için , i j , aşağıdakilerden gibi kısıtlamaları, elde edersiniz hangi yakalama Bundan hiç köşe W j içinde göründüğünü W i . İçin ( x , y ) { ( x j , Y j ) , ( x j + w j , Y j ) , ( x j , YWben,WjbenjWjWben , kısıt oluştur:(x,y){(xj,yj),(xj+wj,yj),(xj,yj+hj),(xj+wj,yj+hj)}

  • .¬(xbenxxben+wjybenyyben+hj)

Şimdiye kadar belirtilen kısıtlamalar, yalnızca ekranın kenarlarına dökülmeyen, bazı minimum boyut kısıtlamalarını karşılayan ve en boy oranını koruyan örtüşmeyen pencereleri açıklar.

İyi bir uyum sağlamak için, iyi bir düzen olmanın ne anlama geldiğini yakalayan bir metrik belirtmeniz gerekir. Bir olasılık, pencerelerin kabaca eşit boyutta olmasını ve / veya "beyaz alanı" en aza indirmek istediğinizi varsaymaktır. Bunun Choco kullanılarak belirtilebileceğini düşünmüyorum, ancak başka bir kısıtlama çözümü ile mümkün olabilir (başka biri burada yardımcı olabilir).

Choco, tek bir değişken olarak belirtilen bir nesnel fonksiyona wrt değerini en üst düzeye çıkarmaya izin verir. Bu fikre dayanarak aşağıdakileri en üst düzeye çıkarabilirsiniz:

  • Σben(hben+wben)

bir kısıtlama yazarak en üst düzeye çıkarmak için Choco ve anlatan C o s t .cÖst=Σben(hben+wben)cÖst


Bu umut verici görünüyor ve bunun nasıl ve ne kadar hızlı olduğunu görmek için kesinlikle Choco ile oynayacağım.
daniel.jackson

Ama neden genel olarak bunu ifade ettiniz? Kısıtlamaları doğrusal eşitsizlikler olarak ifade edebileceğinizi düşünüyorum, yani sahip olduğunuz şey vanilya doğrusal bir programdır.
Suresh

@Suresh: Ayrıntılara girmekten çekinmeyin. Nasıl yapılacağını hemen göremiyorum.
Dave Clarke

1

Bir kaba kuvvet çözümü için bir prototip yazmaya başladım, umarım pratik olacağı bir noktaya kadar optimize edilebilir.

Wwxw,yw,ww,hw

S

Kabaca şöyle çalışır:

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

Geliştirilmesi gereken birkaç şey var:

  • S.coordinates()şu anda çok yavaş. Tüm noktaları yineler S.width x S.heightve her birinin S pencerelerinden birinde olup olmadığını kontrol eder.

  • S.put()Dave'in cevabında belirtilen testi yaparak parametresinin S'nin diğer pencereleriyle çakışıp çakışmadığını kontrol eder. Belki bu aralıklı ağaçlar kullanılarak geliştirilebilir ?

  • S.score()ΣwS.wbenndÖws(hwww)

  • W

Şu anda ekranı ve pencerelerini temsil etmek için uygun bir veri yapısı bulmaya çalışıyorum, bu sorguları desteklemesi gerekiyor:

  • belirli bir pencerenin başkalarıyla çakışmadan konumlandırılabileceği bir koordinat listesi döndürmek
  • x, y konumuna pencere ekle (örtüşmediği zaten doğrulanmış)
  • tüm pencereleri döndür
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.