ฉันมีรูปหลายเหลี่ยม 2 อัน ฉันรู้พิกัดจุดสุดยอดของรูปหลายเหลี่ยมทั้งสอง เป็นวิธีที่ดีที่สุดในการตรวจสอบว่าอย่างใดอย่างหนึ่งอยู่ภายในอื่น ๆ ? ตัวอย่างเช่นอัลกอริทึมควรรับรู้สี่เหลี่ยมคางหมูสีดำด้านล่างว่ามีอยู่:
ฉันมีรูปหลายเหลี่ยม 2 อัน ฉันรู้พิกัดจุดสุดยอดของรูปหลายเหลี่ยมทั้งสอง เป็นวิธีที่ดีที่สุดในการตรวจสอบว่าอย่างใดอย่างหนึ่งอยู่ภายในอื่น ๆ ? ตัวอย่างเช่นอัลกอริทึมควรรับรู้สี่เหลี่ยมคางหมูสีดำด้านล่างว่ามีอยู่:
คำตอบ:
มีตัวอย่างข้อมูลแหล่งที่มามากมายสำหรับวิธีการทดสอบ " จุดในรูปหลายเหลี่ยม " หลักการมาจากทฤษฎีบทโค้งของจอร์แดนสำหรับรูปหลายเหลี่ยม ( 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 แต่ตัดกัน จึงมีบางพื้นที่อยู่ด้านนอก)
หลังจากหนึ่งตรวจสอบอย่างน้อยหนึ่งจุดยอดของรูปหลายเหลี่ยมด้านในให้อยู่ภายในหนึ่งด้านนอกและถ้าไม่มีขอบที่ตัดกันหมายความว่าได้รับเงื่อนไขที่ต้องการแล้ว
ลองทำจุดตัดกับเส้นสีแดงแต่ละเส้น ใน 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
}
อย่างไรก็ตามอย่างที่คุณเห็นโซลูชันนี้จะช้าลงเมื่อคุณเพิ่มรูปหลายเหลี่ยมเพิ่มเติมเพื่อตรวจสอบ วิธีแก้ไขปัญหาอื่นอาจเป็น:
โซลูชันนี้เร็วมาก แต่ขึ้นอยู่กับการนำไปใช้ของคุณ (และสิ่งที่คุณต้องการทำกับผลการตรวจสอบของคุณ) โซลูชันใดที่ทำงานได้ดีที่สุดสำหรับคุณ