Bir çokgenin tamamen diğerini içerip içermediğini nasıl belirlerim?


9

2 çokgenim var. Her iki poligonun tepe koordinatlarını biliyorum. Birinin diğerinin içinde olup olmadığını kontrol etmenin en iyi yolu nedir? Örneğin, algoritma aşağıdaki siyah trapezoid'i içerdiği şekilde tanımalıdır :

örnek çokgenler


Şu anda ayrıntılı bir cevap veremiyorum (bunu daha sonra yapabilir), ancak çarpışma tespiti için ayırma ekseni teoremi için bir uygulamaya bakmalısınız. İstediğinizi kolayca kontrol etmek için algoritma biraz değiştirilebilir. örneğin codezealot.org/archives/55
TravisG

1
Çokgenin içindeki bir çokgenin ne anladığını tam olarak bilemezsiniz. Daha küçük çokgenin tüm noktaları daha büyük olana aitse, ancak her birinin bir çizgide tarafı varsa, bunlar birbirinin içinde midir? i47.tinypic.com/4i0sgg.jpg
speedyGonzales

@speedyGonzales, bu içeride alos.
user960567

Yanıtlar:


5

" Poligon içindeki nokta " için bir test gerçekleştiren bir yöntem için tonlarca kaynak parçacığı vardır . İlke Ürdün'ün çokgenler için eğri teoreminden ( http://www-cgrl.cs.mcgill.ca/~godfried/teaching/cg-projects/97/Octavian/compgeom.html ) gelir.

Naif yol şu olurdu: bu yönteme sahip olmak, şöyle deyin PointInsidePolygon(Point p, Polygon poly):

  bool isInside = true;
  for each (Point p in innerPoly)
  {
    if (!PointInsidePolygon(p, outerPoly))
    {
      isInside = false; // at least one point of the innerPoly is outside the outerPoly
      break;
    }
  }
  if (!isInside) return false;
  // COMPULSORY EDGE INTERSECTION CHECK
  for each (innerEdge in innerPoly)
    for each (outerEdge in outerPoly)
    {
      if (EdgesIntersect(innerEdge, outerEdge))
      {
        isInside = false;
        break;
      }
    }

  return isInside;

Teorik olarak, çokgenleriniz için herhangi bir senaryoyu kaçırmamalı, ancak bu en uygun çözüm değildir.

"Edge" vaka yorumları

  • PointInsidePolygon(..) nokta çokgenin sınırındaysa doğru dönmelidir (ya bir kenarda ya da bir tepe noktasıdır)

  • EdgesIntersect(..)innerEdgeöğesinin bir alt kümesi (geometrik olarak) ise false değerini döndürmelidir outerEdge. Bu durumda, kenarlar açıkça kesişir, ancak algoritmanın amacı için, kesişimin isInsidedeğişkenin arkasındaki anlambilimi kırmadığını belirtmemiz gerekir.

Genel Hatırlatmalar :

  • kenarlarda kenar kesişme kontrolleri olmadan, yorumlarda belirtildiği gibi, yaklaşım bazı içbükey çokgenler için yanlış pozitifler döndürebilir (örneğin V şekilli bir dörtlü ve bir dikdörtgen - dikdörtgen, V şeklinin içindeki tüm köşelerine sahip olabilir, ancak kesişebilir , bu nedenle en azından bazı alanların dışında).

  • iç poligonun köşelerinden en az birinin dış kenarın içinde olup olmadığını kontrol ettikten sonra ve kesişen kenarlar yoksa, aranan koşulun sağlandığı anlamına gelir.


1
Dış çokgen içbükey olduğunda bu yanlış pozitif döndürür.
sam hocevar

2
Yeterince komik, teodron ve şövalye666'lar bireysel olarak yanlış olsa da, birleştirildiklerinde doğru bir cevap vermelidirler. Bir çokgenin tüm noktaları bir diğerinin içindeyse ve çizgileri kesişmiyorsa, ilk poli tamamen diğerinin içindedir.
Hackworth

Doğru, yanlış pozitif döndürür, kenar kavşaklarını da dikkate almalıdır.
teodron

Bu doğru bir cevap gibi görünüyor. Sanırım ikinci döngü durumunu kontrol etmeye gerek yok.
user960567

Bu, uç nokta kavşaklarında veya kenarlar çakışıyorsa çalışmaz.
Brandon Kohn

2

Her kırmızı çizgi ile bir çizgi kesişimi yapmayı deneyin. Sözde kodda:

// loop over polygons
for (int i = 0; i < m_PolygonCount; i++)
{
    bool contained = false;

    for (int j = 0; j < m_Polygon[i].GetLineCount(); j++)
    {
        for (int k = 0; k < m_PolygonContainer.GetLineCount(); k++)
        {
            // if a line of the container polygon intersects with a line of the polygon
            // we know it's not fully contained
            if (m_PolygonContainer.GetLine(k).Intersects(m_Polygon[i].GetLine(j)))
            {
                contained = false;
                break;
            }
        }

        // it only takes one intersection to invalidate the polygon
        if (!contained) { break; }
    }

    // here contained is true if the polygon is fully inside the container
    // and false if it's not
}

Ancak, gördüğünüz gibi, kontrol etmek için daha fazla çokgen ekledikçe bu çözüm yavaşlar. Farklı bir çözüm şunlar olabilir:

  • Kap poligonunu beyaz renkli bir piksel arabelleğine yerleştirin.
  • Bir alt çokgeni beyaz renkle farklı bir piksel arabelleğine oluşturun.
  • Konteyner tamponunu bir XOR maskesi ile poligon tamponu üzerinde maskeleyin.
  • Beyaz piksel sayısını sayın; 0'dan büyükse alt poligon kap tarafından tam olarak kaplanmaz.

Bu çözüm çok hızlıdır, ancak sizin uygulamanıza (ve kontrolünüzün sonucuyla ne yapmak istediğinize) bağlıdır.


1
Çizgi kesişimleri, tam olarak bulunan çokgenleri tespit etmek için yeterli olmayacaktır.
Kylotan

1
Soru: Çokgenler tamamen ayrıksa, hiçbir kenar kesişmez. Bu durumda işe yarar mı? İkinci, grafik tabanlı yaklaşım gerçekten işe yarıyor!
teodron
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.