ฉันจะตรวจสอบได้อย่างไรว่ารูปหลายเหลี่ยมหนึ่งมีอีกรูปแบบหนึ่งอย่างสมบูรณ์?


9

ฉันมีรูปหลายเหลี่ยม 2 อัน ฉันรู้พิกัดจุดสุดยอดของรูปหลายเหลี่ยมทั้งสอง เป็นวิธีที่ดีที่สุดในการตรวจสอบว่าอย่างใดอย่างหนึ่งอยู่ภายในอื่น ๆ ? ตัวอย่างเช่นอัลกอริทึมควรรับรู้สี่เหลี่ยมคางหมูสีดำด้านล่างว่ามีอยู่:

ตัวอย่างรูปหลายเหลี่ยม


ฉันไม่สามารถให้คำตอบอย่างละเอียดได้ในตอนนี้ (อาจทำในภายหลัง) แต่คุณควรดูที่การนำไปใช้สำหรับทฤษฎีแกนการแยกสำหรับการตรวจจับการชนกัน อัลกอริทึมสามารถปรับเปลี่ยนได้เล็กน้อยเพื่อตรวจสอบสิ่งที่คุณต้องการได้อย่างง่ายดาย เช่นcodezealot.org/archives/55
TravisG

1
คุณยังไม่ชัดเจนว่าสิ่งที่คุณเข้าใจเกี่ยวกับรูปหลายเหลี่ยมภายในรูปหลายเหลี่ยม จะเกิดอะไรขึ้นถ้าจุดของรูปหลายเหลี่ยมที่เล็กกว่านั้นอยู่ในจุดที่ใหญ่กว่า แต่แต่ละจุดนั้นมีด้านละหนึ่งเส้น i47.tinypic.com/4i0sgg.jpg
speedyGonzales

@speedyGonzales นี่เรียกว่าข้างใน
user960567

คำตอบ:


5

มีตัวอย่างข้อมูลแหล่งที่มามากมายสำหรับวิธีการทดสอบ " จุดในรูปหลายเหลี่ยม " หลักการมาจากทฤษฎีบทโค้งของจอร์แดนสำหรับรูปหลายเหลี่ยม ( http://www-cgrl.cs.mcgill.ca/~godfried/teaching/cg-projects/97/Octavian/compgeom.html )

วิธีที่ไร้เดียงสาจะ: มีวิธีการที่เรียกว่า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;

ในทางทฤษฎีมันไม่ควรพลาดสถานการณ์ใด ๆ สำหรับรูปหลายเหลี่ยมของคุณ แต่ไม่ใช่ทางออกที่ดีที่สุด

หมายเหตุกรณี "ขอบ"

  • PointInsidePolygon(..) จะต้องคืนค่าจริงถ้าจุดนั้นอยู่บนเส้นขอบของรูปหลายเหลี่ยม (ไม่ว่าจะอยู่บนขอบหรือเป็นจุดยอด)

  • EdgesIntersect(..)ต้องกลับเท็จถ้าinnerEdgeเป็นชุดย่อย (เรขาคณิตที่ชาญฉลาด) outerEdgeของ ในกรณีนี้ขอบตัดอย่างเห็นได้ชัด แต่สำหรับจุดประสงค์ของอัลกอริธึมเราจำเป็นต้องระบุว่าจุดตัดไม่ทำลายความหมายเบื้องหลังisInsideตัวแปร

Remakrs ทั่วไป :

  • โดยไม่มีการตรวจสอบการตัดขอบกับขอบตามที่ระบุไว้ในความคิดเห็นวิธีการอาจส่งคืนผลบวกเท็จสำหรับรูปหลายเหลี่ยมหลายเว้า (เช่นรูปสี่เหลี่ยมรูปตัว V และรูปสี่เหลี่ยมผืนผ้า - รูปสี่เหลี่ยมผืนผ้าอาจมีจุดยอดทั้งหมดภายในรูปร่าง V แต่ตัดกัน จึงมีบางพื้นที่อยู่ด้านนอก)

  • หลังจากหนึ่งตรวจสอบอย่างน้อยหนึ่งจุดยอดของรูปหลายเหลี่ยมด้านในให้อยู่ภายในหนึ่งด้านนอกและถ้าไม่มีขอบที่ตัดกันหมายความว่าได้รับเงื่อนไขที่ต้องการแล้ว


1
สิ่งนี้จะส่งกลับค่าบวกเท็จเมื่อรูปหลายเหลี่ยมด้านนอกเป็นเว้า
sam hocevar

2
ตลกพอในขณะที่ไอโอเทนและอัศวิน 666 นั้นมีความผิดพลาดเป็นรายบุคคลเมื่อรวมกันพวกเขาควรให้คำตอบที่ถูกต้อง หากจุดทั้งหมดของรูปหลายเหลี่ยมอยู่ภายในอีกจุดหนึ่งและหากเส้นของพวกเขาไม่ตัดกันโพลีแรกก็จะอยู่ข้างในอย่างสมบูรณ์
Hackworth

จริงมันจะส่งคืนผลบวกปลอมมันต้องคำนึงถึงจุดตัดขอบบัญชีเช่นกัน
Teodron

นี่ดูเหมือนจะเป็นคำตอบที่ถูกต้อง ฉันคิดว่าไม่จำเป็นต้องตรวจสอบเงื่อนไขลูปที่สอง
user960567

วิธีนี้ใช้ไม่ได้กับจุดตัดกันของจุดปลายหรือหากขอบทับซ้อนกัน
Brandon Kohn

2

ลองทำจุดตัดกับเส้นสีแดงแต่ละเส้น ใน pseudocode:

// 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
}

อย่างไรก็ตามอย่างที่คุณเห็นโซลูชันนี้จะช้าลงเมื่อคุณเพิ่มรูปหลายเหลี่ยมเพิ่มเติมเพื่อตรวจสอบ วิธีแก้ไขปัญหาอื่นอาจเป็น:

  • แสดงรูปหลายเหลี่ยมคอนเทนเนอร์เป็นบัฟเฟอร์พิกเซลด้วยสีขาว
  • แสดงรูปหลายเหลี่ยมลูกไปยังบัฟเฟอร์พิกเซลที่แตกต่างกันด้วยสีขาว
  • มาส์กบัฟเฟอร์คอนเทนเนอร์เหนือบัฟเฟอร์รูปหลายเหลี่ยมด้วยหน้ากาก XOR
  • นับจำนวนพิกเซลสีขาว ถ้ามันมากกว่า 0 รูปหลายเหลี่ยมของเด็กจะไม่ได้อยู่ในภาชนะ

โซลูชันนี้เร็วมาก แต่ขึ้นอยู่กับการนำไปใช้ของคุณ (และสิ่งที่คุณต้องการทำกับผลการตรวจสอบของคุณ) โซลูชันใดที่ทำงานได้ดีที่สุดสำหรับคุณ


1
การตัดกันของเส้นจะไม่เพียงพอที่จะมองเห็นรูปหลายเหลี่ยมที่มีอยู่ครบถ้วน
Kylotan

1
คำถาม: ถ้ารูปหลายเหลี่ยมแยกกันอย่างสมบูรณ์จะไม่มีขอบตัดกัน จะใช้งานได้ในกรณีนี้หรือไม่? วิธีที่สองที่ใช้กราฟิกควรทำงานได้จริง!
Teodron
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.