Izgaradaki döşemelerin kümesinin kapalı bir şekil oluşturup oluşturmadığını belirleme


10

Bir ızgara üzerinde fayans kümesi verildiğinde, belirlemek istiyorum:

  • Fayanslar kapalı bir figür oluşturuyorsa
  • Döşemenin kenarlarını şeklin kenarı olarak saydığınızda, döşemeler kapalı bir şekil yaparsa
  • Önceki iki ifadeden herhangi biri doğruysa, ek karolar ekteki şeklin içine girer ve ilk karolar oluşur.

Oyuncu, bir karo üzerine basıp, aynı renkli karolar zinciri oluşturmak için parmağını diğer karolara sürükleyerek başlayacaktır. Bir sonraki döşemenin geçerli olup olmadığını görmek için giderken kontrol edeceğim. Ör. Oyuncu kırmızı kiremitte başlıyorsa, onların tek sonraki geçerli hamle bitişik kırmızı karo (diyagonallere etmektir yapmak sayımı). Kullanıcı parmağını kaldırdığında, yukarıdaki 3 öğeyi kontrol edebilmem gerekiyor.

Bu yüzden ilk düşüncem, her gittiğimde zincirin geçerliliğini kontrol ettiğimden, oyuncu parmağını kaldırdığında ilk ve son karoların bitişik olup olmadığını kontrol edebileceğimdi. (Ben zaten aynı renk olduklarını biliyorum.) Bitişik olsaydı, kapalı bir figür yaptığım bir önsezim vardı ve buraya büyük bir şey eksik olup olmadığımı görmek için gelecektim ve önsezimin doğru olduğuna dair bir tür mantıksal / matematiksel kanıt (veya yanlış olduğunu kanıtlayan bir örnek).

Ama o zaman 2 numaralı maddeyi düşündüm: Ayrıca, tahtanın kenarını ekteki şeklin bir tarafı olarak kullanan zincirleri de hesaba katmalıyım. Bu durumda, zincirin ilk ve son ürün olacağını değil bitişik olabilir, ama yine de kapalı bir rakam var olacaktır. Şimdi biraz kareye geri döndüm.

Kapalı bir şekil yapıp yapmadıklarını anlamak için bu ızgara koordinatları zinciriyle ne yapabilirim? Bir keresinde Ve do ben kapalı bir rakam var biliyorum, onun sınırları içinde kalan tüm döşemelerin ek listesini almak için en iyi yolu nedir?

resim açıklamasını buraya girin

resim açıklamasını buraya girin

Yukarıda, bu testin 4 olası sonucunun ne olabileceğini umduğum resimleri çizdim.

  1. Zincir kapalı bir şekil oluşturmaz.

  2. Zincir kapalı bir figür yapar.

  3. Tahtanın kenarlarını şeklin kenarı (veya birden fazla kenarı) olarak sayarsanız, zincir kapalı bir rakam yapar.

  4. Zincir ekli bir şekil yapar, ancak oluşturulan şeklin bir parçası olmayan ekstra veri noktaları (kullanıcı tarafından zincirin bir parçası olarak geçerli olarak seçilir) vardır.

Durum 4 en zor olanıdır, çünkü ekteki şekli ve içine düşen parçaları bulmak için "ekstra" zincir bağlantılarını çıkarmanız gerekir (ancak "kapatılmamış" alanın etrafında değil).

Yani ... Herkes bunu çözmek için iyi bir yol, ya da benim için bir başlangıç ​​noktası var mı? Bu noktada bir çember çiziyorum ve başka bir göz seti kullanabilirim.


1
Figür-8 veya pentagram gibi kesişen yollar ne olacak ? Sıfır olmayan veya çift tek doldurma kuralını kabul eder misiniz?
Anko

Vaka 4 ayrıca Vaka 3 ile birleştirilebilir: Ek bilgi ile kartın kenarları kullanılarak
ChargingPun

Tahtanızın ortasından yukarıdan aşağıya doğru dikey bir çizginiz varsa, tahtanın hangi tarafı 'kapalı' olur?
Steven Stadnicki

Şimdilik en küçük alanın kapalı olduğunu varsaymalıyız. OP aksini belirtmedikçe.
Tom 'Blue' Piddock

Yanıtlar:


3

1. fayans bir döngü tespit

Sorun, bir grafikteki bir döngüyü (döngüyü) algılamaya benzer görünüyor, buraya veya buraya bakın .

  • Bu Vgrafiğin düğüm kümesi G=(V, E)döşemelerdir,
  • e = (v1, v2)fayans doğrudan veya çapraz komşularsa, iki farklı düğüm arasında bir kenar vardır

2. Ekran kenarlığı kılıfını kullanma

Ekran kenarlığı, görünür karoların ekranı etrafında tek bir karo genişliğinde jant oluşturacak olan hayali karolardan oluşur.

Spesifikasyonunuza göre ekran kenarlığının bir kısmı kapalı bir döngünün örtük bir parçasını oluşturur. Sadece kapalı bir döngüyü tespit etmek için , bağlantıyı bu kural aracılığıyla onurlandırarak Ggrafiğin grafiğe genişletilmesi yeterli olacaktır G':

  • iki döşemenin her biri doğrudan ekranın kenarına yakın konumlandırılmışsa, iki farklı düğüm arasında başka bir kenar bulunur

Bu nedenle (0,0) ve (1,0) 'daki karolar, "kenar karoları" (-1,0), (-1, -1), (0, -1) ile birlikte kapalı bir döngünün parçası olacaktır. , (1, -1).

3. İlmekli bir alanın iç kısmı

Arthur Wulf White'ın önerdiği şeye benzer bir yöne giderdim :

Döşeme kümesini sınırlamak, döngü döşemelerinin sınırlayıcı kutusuyla incelemek zorundayız.

Daha sonra, sınırlayıcı kutunun içindeki kapalı döngünün dış veya iç mekanı olan tüm karoları seçmek için bir taşkın dolgu kullanın. Bu iki durumdan sadece biri olabilir. Hangisini daha sonra öğrenmeliyiz.

Sınırlayıcı kutuyu her yönde bir kiremitle genişletmek de iyi bir fikir olacaktır extbb, bu da, taşkın dolgusunu bir dış kiremitle başlatmamız durumunda, sadece bir bağlı dış nokta seti ile sonuçlanır.

Taşkın dolgu alanına sahip olduktan sonra sınırlayıcı kutusunu da hesaplayacağız ffbb. Bir dış karo ile başlamamız durumunda, genişletilmiş halka sınırlayıcı kutu ile aynı olmalıdır.

ffbb == extbb

Bir iç döşeme ile başlamamız durumunda, belirgin olarak daha küçük bir sınırlama kutusu vermelidir, çünkü döngü döşemeleri her iki sınırlama kutusu arasında sandviçlenmelidir.

ffbb < extbb

Taşkın dolgusu için başlangıç ​​başlangıç ​​döşemesi, içinde extbbserbest bir döşeme olan herhangi bir döşeme olabilir . Belki rastgele birini seçmek en iyi yaklaşımdır.

Daha önce iç kısmın dış kısımdan daha küçük olduğunu bilseydim, birçok alanın iç kısmında bulunan döngü noktalarının kütle merkezinin etrafında başlardım (karşı örnek: C şekilli alan), aksi takdirde extbb. Ama bunu nasıl tahmin edeceğim konusunda hiçbir fikrim yok.

Son açıklamalar

Normalde, bazı döşemeden başlayan basit bir yürüyüş ve ziyaret edilen döşemelerin bir listesini tutmak bir döngüyü tespit etmek için yeterli olacaktır, ancak bu ekran sınırı koşulu daha karmaşık bir grafik verebilir, bu yüzden bir grafik algoritması ile güvenli tarafta olmalısınız .

Aşağıda iç mekanın bağlı olmadığı bir örnek, diğer taraftan döngü algılaması bu durumda iki döngü bulmalı, biri atılmalıdır.

bazı durumlar


1

Bunu şu şekilde çözebilirsiniz:

  1. Bu şeklin sınırlayıcı kutusunu bulmak.
  2. Boyutunu her yönde 1 arttırmak.
  3. Yeni hafifçe büyütülmüş sınırlayıcı kutunun çerçevesi üzerinde yineleme ve taşkın dolgu uygulaması.
  4. Taşkın dolgusu ile işaretlemediğiniz, o zincirde olmayan herhangi bir fayans varsa, bunlar eklenir. Tanıma göre, şekilden daha fazla kapalı karo varsa, kapalı bir figür olduğunu varsayalım.

Zincirdeki bütün fayans üzerinde biri iterate yapmak ve bulmak onların için minX, minY, maxXve maxYve sizin sınırlama kutusu veya AABB olduğunu.

İki önemsizdir.

Çerçevenin üzerinde yineleme basittir, sadece ızgaranın dışına taşmadığınızdan emin olun. Wikipedia'da nasıl taşkın doldurulacağını öğrenebilirsiniz .

Dört numara için, sadece zincire bitişik karoları kontrol ederek başlayabilirsiniz. Daha fazla kutucuk bulmak için işaretlenmemiş bulduğunuz herhangi bir kutucuğa taşkın dolgu yapabilirsiniz.


0

Kullanıcı zaten seçmiş olduğu bir döşemeyi seçmeye çalıştığında zincirin sona erdiği varsayılarak sezginiz doğrudur. Bu durumda, genel olarak şekil resminizde bir kement gibi görünür (4). Kaydırmaya devam edebilirlerse, birçok döngü çizebilirler ve işler daha karmaşık hale gelir. Yapmak istediğiniz şey çokgen içindeki sorulara cevap vermektir .

İlk olarak, sorunu tanımlamamız gerekiyor. Durumun (2) gibi göründüğünü varsayacağım, yani herhangi bir kuyruk çıkarıldı ve son tekrar başlangıca bağlandı, böylece her karonun tam olarak bir "öncülü" ve tam olarak bir "ardıl" zincirde (X döşemesinin halefinin daima X döşemesi olduğu). Ayrıca, "halefleri" yeterince uzun süre takip ederseniz, sonunda başladığınız yere geri dönersiniz. Gurgadurgen'in önerisini, döngünün herhangi bir noktada gerçekten kendi kendine geri dönüp dönmediğini tespit etmek için kullanabilirsiniz. Kullanıcının girişini, bittiğinde sonlandırdığınızı varsayarsak, bir satırdaki bir dizi düğüm ve ardından bir döngü gibi görünecektir. Döngüyü elde etmek için çizgiyi çıkarabilirsiniz.

Şimdi, her satır için aşağıdakileri yapıyoruz:

  1. Sol kenardan başlayın ve her bir karo için IN veya OUT olup olmadığımızı söyleyen bir boole izleyin. İşe koyulmak.
  2. Geçerli karo, zincirin bir parçasıysa, hem ardılıya hem de selefine (bitişik olması gerekir) bakın. İkisinden biri kesinlikle üzerindeyse (yani, geçerli döşemenin kuzey, kuzey doğu veya kuzey batısı), geçerli döşemenin durumunu soldaki döşemenin tersine ayarlayın. Aksi takdirde, soldaki döşemeyle aynı şekilde ayarlayın. Git 4.
  3. Geçerli kutucuk zincirin bir parçası değilse kutucuğu soldaki başlığın durumuna ayarlayın. Git 4.
  4. Sağdaki karo şimdi geçerli karodur. Git 2.

Şimdi IN olan tüm karoları alın, kenarlıktaki karoları ekleyin (daha önce sıyırdıysanız veya çıkarmadıysanız, bir kuyruk dahil) ve bölgeyi arayın.

Kullanıcının kenarlıkları kullanmasına izin vermek istiyorsanız, bunun kartta tanımlanmadığını ve IN / OUT olmadığını, yalnızca iki parçaya böldüğünü unutmayın. Örneğin, daha küçük bir bölge seçebilir veya kullanıcıdan iki bitişik taraf (ör. Sol ve alt, ancak üst / alt veya sol / sağ değil) kullanmasını isteyebilirsiniz.

Bir optimizasyon, yalnızca içinde kenarlık bulunan satırlar yapmanız gerektiğidir (kenarları kullanamıyorsanız). Tahtanızın her karo üzerinde yinelenmesi ve çok basit bir hesaplama yapmasının en zayıf mobil sistemde bile bir sorun olmadığını kabul ediyorum. (Sonuçta onları bir görev için çok daha karmaşık hale getirmek zorundasınız).

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.