Як розробити алгоритм для розташування (зміни розміру) вікон на екрані, щоб охопити якомога більше місця?


20

Я хотів би написати просту програму, яка приймає набір вікон (ширина + висота) та роздільну здатність екрана і виводить розташування цих вікон на екрані таким чином, що вікна займають найбільше місця. Тому можна змінити розмір вікна, зберігаючи output size >= initial sizeта співвідношення сторін. Отже, для вікна i я хотів би, щоб алгоритм повернув кортеж (x,y,width,height) .

Я вважаю, що це може бути варіантом 2D Рюкзака. Я намагався перебирати результати в Інтернеті, але в основному вони мали багато досвіду (і жодної реалізації), що ускладнювало мене для слідування.

Мене менше цікавить найшвидший алгоритм, але більше - щось, що є практичним для моєї конкретної потреби.


1
Якщо ви змінюєте розмір вікна, я вважаю, що ви не "підтримуєте його початковий розмір", а лише його співвідношення сторін.
Емре

1
Ви можете змінити розмір одного вікна для покриття екрана, в чому проблема?

2
Я другий коментар Саїда. Вам потрібні додаткові обмеження, такі як мінімальні розміри, ціль - мінімізувати суму зміни розмірів, якщо ви хочете виключити тривіальні рішення. Nota bene: математики, схоже, називають проблемою плитковину tessellations .
Рафаель

1
Можливо, краще сказати, ви хочете максимально збільшити мінімальну площу вікна і мінімізувати максимальну область видимого вікна, але конфлікти дозволені чи ні? Будь ласка, відредагуйте своє питання, щоб зробити його помилкою, думати про поточну постановку проблеми непросто.

2
WminwWsize(w)W

Відповіді:


9

Хоча ваше запитання не говорить про це, я припускаю, що ви не хочете, щоб вікна перекривались.

Один із підходів до цієї проблеми - використовувати вирішувач обмежень, такий як Choco . Один просто записує обмеження, що кодують вашу проблему, налаштовує вирішувач на розумний спосіб, а потім нехай він працює. Це означає, що все мислення, що вам потрібно зробити, буде витрачено на пошук хорошого способу кодування проблеми, а не на розробку алгоритму та на програмування та налаштування. Ось часткова відповідь, щоб розпочати роботу.

Припустимо, що розмір екрана становить .xmax×ymax

Для кожного вікна, , ви будете мати набір змінних та обмеженьx i , y i , h i , w iWixi,yi,hi,wi

  • xi,yi,hi,wi0
  • xi+wixmax
  • yi+hiymax
  • Можливо також деякі обмеження щодо мінімального розміру вікон, наприклад, тощо.hi100
  • Обмеження в аспекті: якщо співвідношення сторін дорівнює 3: 4, обмеження може бути чимось на зразок , де - деякий невеликий ненульовий термін помилки, щоб дозволити недосконалий розміри вікон, оскільки в іншому випадку ви перестанете обмежувати проблему.ϵ4hiϵ3wi4hi+ϵϵ

Тепер потрібно подбати про перекриття вікон. Для кожної пари вікон, , де , ви генеруватимете такі обмеження, як наступні, які фіксують, що жоден кут відображається в межах . Для , створюють обмеження:Wi,WjW j W i ( x , y ) { ( x j ,ijWjWi(x,y){(xj,yj),(xj+wj,yj),(xj,yj+hj),(xj+wj,yj+hj)}

  • ¬(xixxi+wjyiyyi+hj) .

Наразі обмеження, описані лише, описують вікна, що не перекриваються, які не розтікаються по сторонах екрана, які задовольняють деяким обмеженням мінімального розміру та зберігають їх співвідношення сторін.

Для того, щоб отримати гарну форму, вам потрібно вказати показник, який фіксує, що означає хороший макет. Однією з можливостей є припущення, що ви хочете, щоб вікна були приблизно однаковими за розмірами та / або що ви хочете мінімізувати "пробіл". Я не думаю, що це можна вказати за допомогою Choco, але це можливо з іншим рішенням обмежень (тут може допомогти хтось інший).

Choco дійсно дозволяє максимізувати wrt до цільової функції, визначеної як одна змінна. Виходячи з цієї ідеї, ви можете досягти максимального наступного:

  • i(hi+wi)

написавши обмеження і сказавши Чоко, щоб максимізувати .c o s tcost=i(hi+wi)cost


Це виглядає багатообіцяюче, і я обов'язково пограю з Choco, щоб побачити, як це працює і як швидко.
daniel.jackson

Але навіщо це взагалі фразувати? Я думаю, що ви можете охарактеризувати обмеження як лінійні нерівності, це означає, що у вас є лінійна програма ванілі.
Суреш

@Suresh: Сміливо розробляйте. Я не відразу бачу, як це зробити.
Дейв Кларк

1

Я почав писати прототип рішення грубої сили, який, сподіваюся, може бути оптимізований до того, що це буде практично.

По-перше, деякі визначення: Нехай - сукупність усіх вікон. Кожне вікно складається з для координат x, y та ширини та висоти. Ініціалізується вікно з мінімальною шириною та висотою.ш х ш , у ш , ш ш , ч шWwxw,yw,ww,hw

Вхід алгоритму - екран , який має ширину та висоту та список вікон.S

Це працює приблизно так:

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

Є кілька речей, які слід вдосконалити:

  • S.coordinates()зараз дуже повільно. Він повторює всі пункти S.width x S.heightта перевіряє, чи є кожен з них у одному з вікон S.

  • S.put()перевіряє, чи перекриває його параметр решта вікон S, роблячи тест, згаданий у відповіді Дейва. Може, це можна покращити за допомогою інтервальних дерев ?

  • S.score()наразі повертає що просто область всіх вікон. Потрібно враховувати інші змінні для створення кращих схем.wS.windows(hwww)

  • Вищенаведена функція повинна спробувати всі перестановки щоб отримати найкращий можливий результат.W

Наразі я намагаюся розробити відповідну структуру даних, яка б представляла екран та його вікна, йому потрібно підтримувати ці запити:

  • повернути список координат, де дане вікно можна розміщувати, не перекриваючись іншими
  • вставити вікно в позицію x, y (вже перевірено, що воно не перетинається)
  • повернути всі вікна
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.