ArcGIS Desktop kullanarak çokgen içindeki çokgenleri paketleme?


25

Bir Boole rasterim var.

Rasterin gri alanlarında, belirli bir boyuttaki poligonu bitişik bir alana sığdırmak istiyorum.

Temel olarak, düzensiz bir poligonum var ve düzensiz poligonun sınırları dahilinde bilinen bir poligonu "sığdırmak" istiyorum.

Çokgenin yönü önemli değil ve bir kare olabilir. Grafiksel olarak sığmasını isterim, ancak sadece poligona (# uygun) bir sayı eklerse de işe yarar.

ArcGIS Desktop 10 kullanıyorum.


8
Bu çok zor bir problem. Mesela bir kareye mümkün olduğunca çok sayıda dairenin sığdırılması çok fazla iş gerektiriyor. Orijinal çokgen karmaşık olduğunda - resimde olduğu gibi - bazı güçlü optimizasyon işlemlerine ihtiyacınız vardır. Bu sorun için bulduğum en iyi yöntem, tavlama simülasyonudur, ancak bu ArcGIS'te mevcut olmayacak ve komut dosyası yazmak için son derece kurnazca bir komut dosyası kullanmanız gerekecekti (ArcGIS çok yavaş). Küçük poligonu mümkün olduğu kadar çok sayıda yerine yeterli sayıda takmak gibi ihtiyaçlarınızı biraz rahatlatabilir misiniz ?
whuber

1
@whuber Gönderimimi düzenlediğiniz için teşekkür ederiz. Evet, yeterli sayıda işe yarar. Veya, belirli bir açı yönünde. ex. yukarıdaki resimde, çokgene o yönde alabildiğim kadar çok sığdırdım, onları bir kez daha sığabilecek kadar 90 derece döndürdüm ...
Thad

1
Evet, ama aynı zamanda tuzaklar ile doludur. Bazıları temel. Örneğin, ESRI tarafından yazılmış ve yayınlanan metin, "ArcView GIS'i Tanımak" (sürüm 3 için), bir futbol sahasını temsil eden bir dikdörtgenin bir çokgenin içine etkileşimli olarak yerleştirildiği bir alıştırma içeriyordu. Sorun, alıştırmanın cevabı yanlıştı çünkü yazar verileri yansıtmayı başaramadı ve coğrafi koordinatları kullanmadaki hataları sonucu etkileyecek kadar büyüktü. Cevap CBS’de iyi görünüyordu, ancak eğer biri bu alanı inşa etmeyi denemiş olsaydı, bunun için yeterli yer olmadığını bulurlardı :-).
whuber

6
@whuber Bir "top parkı" figürünün yeterli olduğunu düşündüler.
Kirk Kuykendall

2
Düzensiz poligonun içindeki düzensiz poligonun genel durumunda, bu hesaplama açısından zorlayıcı bir sorundur: Optimal bir çözüm bulmak her durumda mantıklı bir amaç değildir ve muhtemelen teknik açıdan bakıldığında NP tamamlanmıştır: Bunların önceden belirlenemediği durumlar. Sorunu önemli ölçüde kısıtlarsanız, bazı yinelemeli rastgele uydurma algoritmaları size oldukça yüksek sayılar verebilir . Bu bir ödev ise, doğru cevabı aramamaları, yaratıcı yaklaşımlar arayışı içindeyim.
MappingTumorrow

Yanıtlar:


22

Bu soruna yaklaşmanın birçok yolu vardır. Verinin raster formatı, raster tabanlı bir yaklaşım önerir; Bu yaklaşımları gözden geçirirken, problemin bir ikili tamsayılı lineer program olarak formülasyonu umut verici görünmektedir, çünkü birçok CBS alan seçim analizinin ruhundadır ve bunlara kolayca adapte edilebilir.

Bu formülasyonda, "fayans" olarak adlandıracağım dolum poligonunun (lar) mümkün olan tüm pozisyonlarını ve yönlerini sıralıyoruz. Her karo ile ilişkili "iyiliğinin" bir ölçüsüdür. Amaç, toplam iyiliği mümkün olduğu kadar büyük olan üst üste binmeyen karolardan oluşan bir koleksiyon bulmaktır. Burada, her döşemenin iyiliğini kapsadığı alan olarak alabiliriz. (Daha fazla veri bakımından zengin ve sofistike karar ortamlarında, iyiliği, her bir döşemenin içerdiği hücrelerin özelliklerinin, belki de görünürlükle ilgili özelliklerin, diğer şeylerin yakınlığına vb. Bağlı olarak hesaplıyor olabiliriz.)

Bu problem üzerindeki kısıtlamalar basitçe, bir çözelti içindeki hiçbir iki döşemenin üst üste gelemeyeceğidir.

Bu, doldurulacak poligondaki hücrelerin sayılmasıyla ("bölge") 1, 2, ..., M , verimli bir şekilde hesaplanmaya elverişli bir şekilde biraz daha soyut olarak çerçevelenebilir . Herhangi bir kiremit yerleşimi, sıfırların ve diğerlerinin bir gösterge vektörüyle kodlanmış olabilir, bu da diğerlerinin kiremit ve sıfırlarla kaplı hücrelere karşılık gelmesine izin verir. Bu kodlamada, bir kiremit koleksiyonu hakkında gerekli tüm bilgiler gösterge vektörlerini toplayarak bulunabilir (her zamanki gibi bileşene göre bileşen): toplam, en az bir döşemenin bir hücreyi kapsadığı ve toplamın daha büyük olacağı yerlerde sıfırdan farklı olacaktır iki veya daha fazla fayans üst üste binen birden fazla yerde. (Toplam, örtüşme miktarını etkili bir şekilde sayar.)

Bir daha küçük soyutlama: Olası karo yerleşim kümesi kendisi sayılan demek olabilir 1, 2, ..., N . Herhangi bir kiremit yerleşimi kümesinin kendisinin seçimi, yerlilerin yerleştirilecek kiremitleri belirlediği bir gösterge vektörüne karşılık gelir.

İşte fikirleri düzeltmek için küçük bir örnek . Hesaplamaları yapmak için kullanılan Mathematica koduna eşlik eder , böylece programlama zorluğu (veya eksikliği) açıkça ortaya çıkar.

İlk olarak, döşenecek bir bölgeyi gösterelim:

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

Şekil 1: bölge

Hücrelerini soldan sağa doğru numaralandırırsak, en baştan başlayarak, bölge için gösterge vektörünün 16 girişi vardır:

Flatten[region]

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

Aşağıdaki döşemeyi, tüm dönüşlerde 90 derecenin katları ile birlikte kullanalım:

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

Şekil 2: Döşeme

Rotasyon (ve yansımalar) oluşturmak için kod:

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]];

(Bu biraz opak hesaplama, bir döşemenin tüm olası dönüşlerini ve yansımalarını gösterdiğini ve sonra yinelenen sonuçları kaldırdığını gösteren /math//a/159159 adresindeki bir yanıtta açıklanmıştır .)

Döşemeyi burada gösterildiği gibi yerleştireceğimizi varsayalım:

Şekil 3: Karo yerleşimi

Bu yerleşimde 3, 6 ve 7 numaralı hücreler kaplanmıştır. Bu gösterge vektörü tarafından belirlenir

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

Bu döşemeyi bir sütunu sağa kaydırırsak, bu gösterge vektörü bunun yerine

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

Fayansları her iki konuma aynı anda yerleştirmeye çalışmanın kombinasyonu , bu göstergelerin toplamı tarafından

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

Yedinci pozisyondaki 2, bu örtüşmeyi bir hücrede gösterir (ikinci satır aşağı, soldan üçüncü sütun). Örtüşmek istemediğimiz için, herhangi bir geçerli çözümdeki vektörlerin toplamının 1'i geçmemesi gerekir.

Bu problem için fayanslar için 29 oryantasyon ve pozisyon kombinasyonunun mümkün olduğu ortaya çıktı. (Bu, ayrıntılı bir araştırmayı içeren basit bir kodlama biti ile bulundu.) Göstergelerini sütun vektörleri olarak çizerek 29 olasılığı da gösterebiliriz . (Satır yerine sütunları kullanmak gelenekseldir.) İşte, 16 satır (dikdörtgendeki her olası hücre için bir tane) ve 29 sütuna sahip olan sonuç dizisinin bir resmi:

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];

Şekil 4: seçenekler dizisi

(Önceki iki gösterge vektörü soldaki ilk iki sütun olarak görünür.) Keskin gözlü okuyucu paralel işleme için çeşitli fırsatlar fark etmiş olabilir: bu hesaplamalar birkaç saniye sürebilir.

Yukarıdakilerin tümü, matris notasyonu kullanılarak kompakt bir şekilde yeniden düzenlenebilir:

  • F , M satırı ve N sütunu olan bir seçenek dizisidir .

  • X , N uzunluğundaki bir dizi döşeme yerleşiminin göstergesidir .

  • b , bir N- vektörüdür.

  • R , bölgenin göstergesidir; bir olduğunu M -vector.

Mümkün olan herhangi bir X çözeltisiyle ilişkilendirilen toplam "iyilik" , RFX'e eşittir , çünkü FX , X'in kapsadığı hücrelerin göstergesidir ve R'nin olduğu ürün bu değerleri toplar. ( Bölgedeki belirli alanları tercih etmek ya da önlemek için çözümler diliyorsak, R'yi ağırlıklandırabiliriz .) Bu maksimize edilecektir. Çünkü biz bunu ( RF ) olarak yazabiliriz . X , bir olan doğrusal fonksiyonu X : Bu önemli. (Aşağıdaki kodda, değişken RFc içerir .)

Kısıtlamaları vardır o

  1. X'in tüm unsurları negatif olmamalıdır;

  2. X'in tüm elemanları 1'den küçük olmalıdır ( b'deki karşılık gelen giriş );

  3. X'in tüm unsurları ayrılmaz olmalıdır.

Kısıtlayıcı (1) ve (2) bu yapmak doğrusal program üçüncü gereklilik, içine döner iken, tamsayı programı lineer.

Tam olarak bu şekilde ifade edilen tamsayılı doğrusal programları çözmek için birçok paket vardır . Onlar M ve N değerlerini onlarca, hatta yüzbinlerce üzerinde tutabiliyorlar. Bazı gerçek dünya uygulamaları için bu muhtemelen yeterince iyi.


İlk resmimiz olarak, önceki örnekte Mathematica 8'in LinearProgrammingkomutunu kullanarak bir çözüm hesapladım . (Bu, doğrusal bir amaç işlevini en aza indirir . Amaç, işlev işlevini reddederek minimize etme kolayca maksimize olur.) 0.011 saniyede bir çözüm (karoların ve konumlarının listesi olarak) döndürür:

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 &]]];

Şekil 5: çözüm

Gri hücreler hiç bölgede değil; beyaz hücreler bu çözeltiyle kaplanmadı.

Bu kadar iyi olan birçok başka tiltleri (el ile) çözebilirsiniz - ama daha iyisini bulamazsınız. Yani bu yaklaşımın potansiyel bir sınırlama var: size verir bir en iyi çözümü, birden fazla olduğunda bile. (Bazı geçici çözümler vardır: X'in sütunlarını yeniden sıralarsak, sorun değişmeden kalır, ancak yazılım sonuç olarak farklı bir çözüm seçer. Ancak, bu davranış tahmin edilemez.)

İkinci bir örnek olarak , daha gerçekçi olmak için, söz konusu bölgeyi düşünelim. Görüntüyü içe aktararak ve yeniden örnekleyerek, onu 69'a 81 ızgarayla temsil ettim:

Şekil 6: Bölge

Bölge, bu ızgaradan 2156 hücre içerir.

İşleri ilginç kılmak ve doğrusal programlama kurulumunun genelliğini göstermek için, bu bölgeyi olabildiğince iki çeşit dikdörtgenle kapatalım:

Şekil 7: fayans

Biri 17'e 9 (153 hücre), diğeri 15'e 11 (165 hücre). İkincisi kullanmayı tercih edebiliriz, çünkü daha büyük, ancak birincisi daha ince ve daha dar yerlere sığabilir. Bakalım!

Program şimdi N = 5589 olası kiremit yerleşimini içeriyor . Bu oldukça büyük! 6.3 saniyelik bir hesaplamadan sonra, Mathematica bu on döşemeli çözümle geldi:

Şekil 8: Çözüm

Bazı gevşeklikler nedeniyle ( .eg, sol alt karoyu sola doğru dört sütuna kaydırabiliriz), açıkça ondan biraz farklı olan başka çözümler de var.


1
Bu çözümün daha önceki bir sürümü (ancak bu kadar iyi değil) , mathematica.stackexchange.com/a/6888 adresindeki Mathematica sitesinde görünüyor . Bölgenin olabildiğince az kiremitle tamamen kaplanması sorununu çözmek için formülasyonda küçük bir varyasyonun (elbette bazı örtüşmelere izin veriyor) çözülmesi de dikkate değer olabilir: bu "çukur yamalarını" çözecektir. sorun.
whuber

1
Alanın çıkarlarına göre, bu cevap potansiyel olarak faydalı bazı iyileştirmeler tanımlamaz. Örneğin, olası tüm döşeme konumlarını (gösterge vektörleri olarak) bulduktan sonra, hangi hücrelerin gerçekte bir kiremit tarafından kaplanabileceğini bulmak için hepsini ekleyebilirsiniz. Bu tür hücrelerin kümesi, ikinci örnekte iki ayrı bağlı bileşene bölünür. Bu, sorunun iki bileşenden bağımsız olarak çözülebileceği ve büyüklüğünü (ve dolayısıyla hesaplama süresini) büyük ölçüde azaltacağı anlamına gelir. Bu tür basitleştirmeler gerçek dünyadaki sorunların üstesinden gelmede önemli olma eğilimindedir.
whuber

Büyük çaba ve cevap. Chris'in cevabı da yardımcı oldu. Yardımlarınız için herkese teşekkürler! Çalışıyor ve yine doğru yönde hareket etmemi sağladı.
Thad

Vaov! Benzer bir sorunla ilgileniyordum ve bu yazı bana yeni bir bakış açısı kazandırdı. Teşekkür ederim. Eğer R daha büyükse (örneğin 140x140≈20000), hesaplama maliyetini azaltmanın herhangi bir yolu var mı? Bu sorunla ilgili herhangi bir makale biliyor musunuz? Arama anahtar kelimelerim beni doğru şekilde yönlendirmiyor (şimdiye kadar).
nimcap

@ nimcap Bu önemli bir problem sınıfıdır, çok fazla araştırma devam ediyor. Aranacak anahtar kelimeler "karma tamsayılı doğrusal program" ile başlar ve bulduklarınıza göre oradan ayrılır.
whuber

5

Link Çokgenler ambalajlama için Açık Genetik Algoritmalar sağlanan, benim cevap benzer bir soruya asgari aralıklarla kısıtlı alan içinde noktalarının yer maksimum sayıda algoritma Aradığınız? faydalı olabilir. Metot isteğe bağlı konteyner şekilleriyle (ve sadece dikdörtgenler değil) çalışmak üzere genelleştirilebilir gibi görünüyor.


Bu makalenin bazı güzel fikirleri var (+1), ancak tüm algoritmaları, temelde, çokgenleri dikdörtgen bölgeler içinde paketlemeye odaklanıyor . Bunun nedeni, çokgenlerin karenin kenarlarına paralel olarak belirlenmiş bir köşeye doğru kaydırıldığı bir dizi prosedürü temsil eden ayrı bir veri yapısına sahip (bir dizi çokgen dizisi) olan paketleri temsil etmesidir . Böyle basit bir ayrık kodlamanın daha karmaşık bölgeler için daha az etkili olacağı anlaşılmaktadır. Belki de şebekedeki bölgelerin başlangıçtaki basitleştirilmesi yardımcı olacaktır.
whuber

2

Bahsettiğiniz oldukça kısıtlanmış alt küme için (bir çukurda kare / üçgen döşeme), yukarıdaki açık optimizasyonları varsayalım, bu sözde kodun, sizi problemi zorlayan yüksek çözünürlüklü olasılıklarla alıp götürerek yaklaşık bir cevaba ulaşması gerekir. Dikdörtgen fayanslar veya oldukça düzensiz bir konteyner gibi, tek tek fayans rotasyonunun kazanımları görebileceği durumlar için doğru çalışmayacaktır. Bu 1 milyon yinelemedir, gerekirse daha fazla deneyebilirsiniz.

L uzunlukları olan bir kare kabul edin

En azından kabın ölçüsünün boyutlarından biri olan karelerden oluşan bir dama tahtası deseni ve her bir yönde en az 1L oluşturun.

N = 0

DX = 0

DY = 0

DR = 0

Dama tahtası pozisyonunu orijinal centroid'e sıfırla

(R = 1: 100) için

(Y = 1: 100) için

(X = 1: 100) için

M = Tamamen kabın içindeki kare sayısını say

Eğer (M> N)

DR = R,

DY = Y

DX = X

K = M

Dama Tahtasını Doğuya L / 100 ile kaydır

Dama doğusunu sıfırla

Dama Tahtasını Kuzeye Taşı / L / 100

Dama tahtası kuzeyini sıfırla

Dama tahtasını merkezini etrafında 3,6 derece CW döndür

DY = DY * L

DX = DX * L

Dama tahtasını orijinal konumuna ve döndürmeye sıfırla

DR & "," & DX & "ve" & DY & "ifadelerini yazdır, son çeviri / döndürme matrisidir"

Dama tahtası döndürerek DR

Dama, DY

Tamamen kabın içinde olan kareleri seçin.

Kareleri dışa aktar


Bu prosedürü, bir uzun kenarın ortasındaki bir hücre eksik olan 2 ila 5 bölgede denerseniz, içine sadece bir 2 ila 2 kare koyabileceğinizi göreceksiniz. Bununla birlikte, bu gibi iki kare kolayca sığabilmektedir. Sorun, normal bir "dama tahtası" düzeninin parçası olmamasıdır. Bu zorluk, bu sorunu oldukça zorlaştıran şeylerden biridir.
whuber

1
Evet. Her biri birkaç hücre sırasına göre çok sayıda bitişik olmayan düzenli modeli destekleyebilecek kadar düzensiz bir kap şekline sahipseniz, bu, optimal olmaktan çok uzaktadır. Olası boşluğa bunun gibi şeyler eklemek, işlem süresini çok hızlı bir şekilde artırır ve hedeflediğiniz özel durum için belirli bir düzeyde planlama gerektirir.
MappingTumorrow
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.