Упаковка полігонів у полігон за допомогою ArcGIS Desktop?


25

У мене булевий растр.

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

В основному, у мене неправильний багатокутник, і я хотів би якомога більше разів «помістити» відомий багатокутник в межах неправильного багатокутника.

Напрямок багатокутника не має значення, і це може бути квадрат. Я хотів би, щоб він підходив графічно, але якби він просто прикріпив номер до багатокутника (# що підходить), він би також працював.

Я використовую ArcGIS Desktop 10.


8
Це дуже важка проблема. Потрібно багато роботи, щоб, наприклад, розмістити якомога більше кіл на квадрат. Коли оригінальний багатокутник є складним - як на ілюстрації - вам потрібні кілька потужних процедур оптимізації. Найкращий метод, який я знайшов для цієї проблеми, - це імітаційний відпал, але він не буде доступний в ArcGIS, і для його сценарію знадобиться надзвичайно хитрі сценарії (ArcGIS занадто повільний). Не могли б ви трохи розслабити свої вимоги, наприклад, встановити менший багатокутник достатньо разів, а не якомога більше разів?
whuber

1
@whuber Дякую за редагування моєї публікації. Так, достатня кількість разів працювала б. Або як щодо заданої кутової орієнтації. колишній на зображенні вище я помістив багатокутник стільки разів, скільки міг би мати в цій орієнтації, якби я повернув їх на 90 градусів, ти міг би встановити ще один ...
Тад,

1
Так, але це також загрожує підводними каменями. Деякі - елементарні. Наприклад, текст з авторським та опублікованим ESRI текстом "Знайомство з ArcView GIS" (для версії 3) включав вправу, в якій прямокутник, що представляє футбольне поле, був інтерактивно розміщений у полігоні. Проблема полягала в тому, що відповідь вправи була помилковою, оскільки автор не спроектував дані, а помилки у використанні географічних координат були досить великими, щоб вплинути на результат. Відповідь виглядала добре в ГІС, але якби хто-небудь спробував побудувати це поле, знайшов би, що для цього було недостатньо місця :-).
whuber

6
@whuber Я думаю, вони вважали, що цифра "парку кулі" є достатньою.
Кірк Куйкендалл

2
У загальному випадку нерегулярного багатокутника в межах неправильного багатокутника це обчислювально нерозв'язна проблема: Пошук оптимального рішення не є правдоподібною метою у всіх випадках, і, ймовірно, NP-завершений з технічної точки зору: Які випадки не можуть бути заздалегідь визначені. Якщо ви значно обмежуєте проблему, деякі ітеративні алгоритми випадкової підгонки, ймовірно, дадуть вам досить високі цифри. Моє відчуття, якщо це завдання - це те, що вони не шукають правильної відповіді, вони шукають творчих підходів.
КартографуванняЗавтра

Відповіді:


22

Існує багато способів підходу до цієї проблеми. Растровий формат даних передбачає растровий підхід; при перегляді цих підходів формулювання проблеми як бінарної цілочислової лінійної програми виглядає перспективною, оскільки це дуже відповідає духу багатьох аналізів вибору сайтів ГІС і може легко адаптуватися до них.

У цій рецептурі перераховуємо всі можливі положення та орієнтації наповнюючих полігонів (ів), які я буду називати "плитками". Пов’язана з кожною плиткою міра її «доброти». Мета полягає в тому, щоб знайти колекцію плит, що не перекриваються, загальна корисність якомога більша. Тут ми можемо сприйняти користь кожної плитки як площу, яку вона покриває. (У більш багатих даними та складних середовищах прийняття рішень ми можемо обчислювати доброту як сукупність властивостей комірок, що входять до кожної плитки, властивостей, можливо, пов'язаних із видимістю, близькістю до інших речей тощо).

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

Це може бути оформлена трохи більше абстрактно, таким чином , сприяє ефективному обчисленню, шляхом перерахування осередків на полігоні повинні бути заповнені (в «область») 1, 2, ..., M . Будь-яке розміщення плитки може бути кодоване індикаторним вектором нулів та розмірів, дозволяючи тим, що відповідають клітинкам, покритим плиткою та нулями в інших місцях. У цьому кодуванні всю інформацію, необхідну про колекцію плиток, можна знайти, підсумовуючи їхні показники векторів (компонент за складовою, як зазвичай): сума буде ненульовою саме там, де принаймні одна плитка покриває клітинку, і сума буде більшою ніж десь дві або більше плиток перекриваються. (Сума фактично підраховує суму перекриття.)

Ще одна маленька абстракція: безліч можливих місць розміщення плитки саме можна перерахувати, скажімо , 1, 2, ..., N . Вибір будь-якого набору розміщення плиток сам відповідає індикаторному вектору, де ті позначають плитку для розміщення.

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

По-перше, ми зобразимо область, яку потрібно підкласти черепицею:

region =  {{0, 0, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}};

Малюнок 1: регіон

Якщо пронумерувати його клітинки зліва направо, починаючи з верху, індикаторний вектор для регіону має 16 записів:

Flatten[region]

{0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}

Давайте використовувати наступну плитку разом з усіма обертаннями кратними 90 градусам:

tileSet = {{{1, 1}, {1, 0}}};

Малюнок 2: плитка

Код для генерації обертів (і відображень):

apply[s_List, alpha] := Reverse /@ s;
apply[s_List, beta] := Transpose[s];
apply[s_List, g_List] := Fold[apply, s, g];
group = FoldList[Append, {}, Riffle[ConstantArray[alpha, 4], beta]];
tiles = Union[Flatten[Outer[apply[#1, #2] &, tileSet, group, 1], 1]];

(Цей дещо непрозорий обчислення пояснюється у відповіді за адресою /math//a/159159 , де показано, що він просто створює всі можливі повороти та відображення плитки, а потім видаляє всі повторювані результати.)

Припустимо, ми повинні розмістити плитку, як показано тут:

Малюнок 3: розміщення плитки

Клітини 3, 6 і 7 охоплені в цьому місці. Це позначається індикаторним вектором

{0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}

Якщо перенести цю плитку на один стовпчик праворуч, то цей індикаторний вектор був би

{0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0}

Поєднання спроб розмістити плитку в обох цих положеннях одночасно визначається сумою цих показників,

{0, 0, 1, 1, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0}

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

Виявляється, для цієї проблеми для плиток можливі 29 комбінацій орієнтації та положення. (Це було виявлено за допомогою простого біта кодування, що включає вичерпний пошук.) Ми можемо зобразити всі 29 можливостей, намалювавши їх показники як вектори стовпців . (Використання стовпців замість рядків є звичайним.) Ось зображення отриманого масиву, який матиме 16 рядків (по одному для кожної можливої ​​комірки у прямокутнику) та 29 стовпців:

makeAllTiles[tile_, {n_Integer, m_Integer}] := 
  With[{ m0 = Length[tile], n0 = Length[First[tile]]},
   Flatten[
    Table[ArrayPad[tile, {{i, m - m0 - i}, {j, n - n0 - j}}],  {i, 0, m - m0}, {j, 0, n - n0}], 1]];
allTiles = Flatten[ParallelMap[makeAllTiles[#, ImageDimensions[regionImage]] & , tiles], 1];
allTiles = Parallelize[
   Select[allTiles, (regionVector . Flatten[#]) >= (Plus @@ (Flatten[#])) &]];
options = Transpose[Flatten /@ allTiles];

Малюнок 4: масив параметрів

(Попередні два індикаторні вектори виглядають як перші два стовпчики зліва.) Гострозубий читач, можливо, помітив кілька можливостей для паралельної обробки: ці обчислення можуть зайняти кілька секунд.

Все вищесказане можна компактно перезапустити за допомогою матричних позначень:

  • F - це масив параметрів з M рядками та N стовпцями.

  • Х є індикатором набору плитки розміщень, довжини N .

  • b - N- вектор одиниць.

  • R - показник для регіону; це М- вектор.

Загальна «доброта», пов'язана з будь-яким можливим рішенням X , дорівнює RFX , оскільки FX - це показник клітин, охоплених X, а продукт з R підсумовує ці значення. (Ми могли б зважити R, якби побажали, щоб рішення сприяли або уникали певних районів регіону.) Це потрібно максимально використовувати. Тому що ми можемо записати це як ( РФ ). X , це лінійна функція X : це важливо. (У наведеному нижче коді змінна cмістить РФ .)

Ці обмеження є , що

  1. Усі елементи X повинні бути негативними;

  2. Усі елементи X повинні бути меншими за 1 (що є відповідним записом у b );

  3. Усі елементи X повинні бути цілісними.

Обмеження (1) та (2) роблять цю програму лінійною , тоді як третя вимога перетворює її на цілу лінійну програму.

Існує багато пакетів для вирішення цілих лінійних програм, виражених саме в цій формі. Вони здатні обробляти значення M і N в десятки, а то й сотні тисяч. Це, мабуть, досить добре для деяких реальних програм.


Як наша перша ілюстрація, я обчислював рішення для попереднього прикладу, використовуючи команду Mathematica 8 LinearProgramming. (Це дозволить мінімізувати лінійну цільову функцію. Мінімізація легко перетворюється на максимізацію шляхом відмови від цільової функції.) Він повернув рішення (як список плиток та їх позицій) за 0,011 секунд:

b = ConstantArray[-1, Length[options]];
c = -Flatten[region].options;
lu = ConstantArray[{0, 1}, Length[First[options]]];
x = LinearProgramming[c, -options, b, lu, Integers, Tolerance -> 0.05];
If[! ListQ[x] || Max[options.x] > 1, x = {}];
solution = allTiles[[Select[x Range[Length[x]], # > 0 &]]];

Фіг.5: розчин

Сірі клітини взагалі відсутні в регіоні; білі клітини не були покриті цим розчином.

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

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

Рисунок 6: Регіон

Регіон включає 2156 осередків цієї сітки.

Щоб зробити речі цікавими та проілюструвати загальність установки лінійного програмування, спробуємо охопити якомога більше цієї області двома видами прямокутників:

Малюнок 7: плитка

Один - 17 на 9 (153 клітини), а другий - 15 на 11 (165 клітин). Ми можемо вважати за краще використовувати другий, тому що він більший, але перший є більш худим і може вміститися в тісніших місцях. Побачимо!

Зараз програма передбачає N = 5589 можливих розміщення плитки. Він досить великий! Після 6,3 секунди обчислення, Mathematica придумала це рішення з десяти плиток:

Малюнок 8: розчин

З - за деяку слабину ( .eg, ми могли б зрушити ліву нижню плитку до чотирьох стовпців зліва від нього ), є , очевидно , деякі інші рішення , що трохи відрізняються від цього.


1
Більш рання версія цього рішення (але не настільки хороша) з’являється на сайті Mathematica за адресою mathematica.stackexchange.com/a/6888 . Можливо, варто також зазначити, що незначна варіація рецептури може бути використана для вирішення проблеми повного покриття області якомога менше плиток (що дозволяє, звичайно, допускати деякі перекриття): це дозволить вирішити "випадання вибоїн" проблема.
whuber

1
В інтересах простору ця відповідь не описує потенційно корисних удосконалень. Наприклад, знайшовши всі можливі позиції плитки (як індикатори векторів), ви можете додати їх усе, щоб знайти, які клітини насправді можуть бути покриті певною плиткою. Набір таких комірок розбивається на два окремих з'єднані компоненти у другому прикладі. Це означає, що проблему можна самостійно вирішити в двох компонентах, істотно зменшивши її розмір (і, отже, обчислюючи час). Такі початкові спрощення, як правило, важливі для вирішення проблем у реальному світі.
whuber

Великі зусилля та відповідь. Відповідь Кріса також була корисною. Дякую всім за допомогу! Працює, і я знову рухаюсь у правильному напрямку.
Тад

Оце Так! Мене зацікавила подібна проблема, і ця посада дала мені нову перспективу. Дякую. Що робити, якщо R більший (наприклад, 140x140≈20000), чи існують способи зменшити витрати на обчислення? Чи знаєте ви якісь документи, пов'язані з цією проблемою? Мої ключові слова пошуку не ведуть мене до правильного шляху (до цих пір).
nimcap

@nimcap Це важливий клас проблем, тому триває багато досліджень. Ключові слова для пошуку починалися б із "змішаної цілолінійної лінійної програми" та розв'язувалися звідти на основі того, що ви знайдете.
whuber

5

Посилання на генетичні алгоритми пакування багатокутників , надані у моїй відповіді на аналогічне запитання за алгоритмом пошуку шукати максимальну кількість балів у обмеженій області при мінімальному відстані? , може бути корисним. Схоже, метод може бути узагальнений для роботи з довільними формами контейнерів (а не лише прямокутниками).


У цьому документі є кілька приємних ідей (+1), але всі його алгоритми принципово орієнтовані на упаковку полігонів у прямокутних областях. Це пояснюється тим, що він представляє упаковки з дискретною структурою даних (послідовність багатокутників разом з їх орієнтаціями), яка являє собою набір процедур, в яких багатокутники ковзають , паралельно сторонам квадрата, до визначеного кута. Здається, що таке просте дискретне кодування було б менш ефективним для складніших регіонів. Можливо, допоможе початкове спрощення регіонів мережі.
whuber

2

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

Припустимо квадрат зі сторонами довжиною L

Створіть шаблон квадратиків, який має принаймні розміри розміру контейнера плюс не менше 1 л у кожному напрямку.

N = 0

DX = 0

DY = 0

DR = 0

Скиньте положення контрольної дошки до початкового центру

Для (R = 1: 100)

Для (Y = 1: 100)

Для (X = 1: 100)

M = Порахуйте кількість квадратів повністю в контейнері

Якщо (M> N)

DR = R

DY = Y

DX = X

N = M

Перемістіть шахматну дошку на схід на L / 100

Скиньте шахову дошку на схід

Перемістіть шахматну дошку на північ на L / 100

Скиньте шахівницю

Обертайте шахматну дошку на 3,6 градуса СВ навколо її центру

DY = DY * L

DX = DX * L

Скиньте контрольну дошку до вихідного положення та обертання

Друкувати DR & "," & DX & "та" & DY & "- це остаточна матриця перекладу / обертання"

Поверніть шахівницю DR

Перекласти шахівницю на DX, DY

Виберіть квадрати, які повністю знаходяться в контейнері

Експорт квадратів


Якщо ви спробуєте цю процедуру на ділянці 2 на 5, а комірка відсутня посередині одного довгого краю, ви побачите, що можете помістити в неї лише один 2 на 2 квадрат. Однак два такі квадрати легко вміщуються. Проблема полягає в тому, що вони не є частиною звичайного шаблону «шахівниці». Ця складність є однією з речей, яка робить цю проблему досить важкою.
whuber

1
Так. Якщо у вас форма контейнера достатньо нерегулярна, щоб він міг підтримувати декілька суперечливих регулярних шаблонів на порядок у декількох клітинках кожна, це закінчується дуже далеко від оптимального. Додавання подібних речей до можливостей простору збільшує час обробки та вимагає певного планування для конкретного випадку, на який ви орієнтуєтесь.
КартографуванняЗавтра
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.