Làm cách nào để xác định xem một đa giác có chứa hoàn toàn khác không?


9

Tôi có 2 đa giác. Tôi biết tọa độ đỉnh của cả hai đa giác. Cách tốt nhất để kiểm tra xem cái này có hoàn toàn bên trong cái kia không? Ví dụ, thuật toán chỉ nên nhận ra hình thang màu đen bên dưới như được chứa:

đa giác ví dụ


Tôi không thể đưa ra câu trả lời chi tiết ngay bây giờ (có thể làm điều đó sau), nhưng bạn nên xem qua một triển khai cho định lý trục tách để phát hiện va chạm. Thuật toán có thể được sửa đổi một chút để dễ dàng kiểm tra những gì bạn muốn. ví dụ codezealot.org/archives/55
TravisG

1
Bạn không chính xác rõ ràng những gì bạn hiểu về một đa giác bên trong đa giác. Điều gì sẽ xảy ra nếu tất cả các điểm của đa giác nhỏ hơn nằm trong một điểm lớn hơn, nhưng mỗi điểm có một cạnh trên một đường thẳng, chúng có nằm trong nhau không? i47.tinypic.com/4i0sgg.jpg
speedyGonzales

@speedyGonzales, đây là alos được gọi là bên trong.
dùng960567

Câu trả lời:


5

Có hàng tấn đoạn mã nguồn cho một phương thức thực hiện kiểm tra " điểm bên trong đa giác ". Nguyên tắc này xuất phát từ định lý đường cong của Jordan cho đa giác ( http://www-cgrl.cs.mcgill.ca/~godfried/teaching/cg-projects/97/Octavian/compgeom.html ).

Cách ngây thơ sẽ là: có phương pháp đó, gọi nó là 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;

Về mặt lý thuyết, nó không nên bỏ lỡ bất kỳ kịch bản nào cho đa giác của bạn, nhưng đó không phải là giải pháp tối ưu.

Nhận xét trường hợp "Cạnh"

  • PointInsidePolygon(..) phải trả về true nếu điểm nằm trên đường viền của đa giác (nằm trên một cạnh hoặc là một đỉnh)

  • EdgesIntersect(..)phải trả về false nếu innerEdgelà tập hợp con (thông minh về mặt hình học) của outerEdge. Trong trường hợp này, các cạnh rõ ràng giao nhau, nhưng với mục đích của thuật toán, chúng ta cần chỉ ra rằng giao điểm không phá vỡ ngữ nghĩa đằng sau isInsidebiến

Đại tướng quân :

  • không có kiểm tra giao điểm cạnh và cạnh, như đã nêu trong các nhận xét, cách tiếp cận có thể trả về giá trị dương cho một số đa giác lõm (ví dụ hình tứ giác hình chữ V và hình chữ nhật - hình chữ nhật có thể có tất cả các đỉnh của nó bên trong hình chữ V, nhưng giao nhau , do đó có ít nhất một số khu vực bên ngoài).

  • sau khi kiểm tra ít nhất một trong các đỉnh của đa giác bên trong nằm bên trong bên ngoài và nếu không có các cạnh giao nhau, điều đó có nghĩa là điều kiện tìm kiếm được thỏa mãn.


1
Điều này sẽ trả về dương tính giả khi đa giác bên ngoài bị lõm.
sam hocevar

2
Hài hước lắm, trong khi cá nhân của teodron và hiệp sĩ sai là cá nhân, khi kết hợp lại, họ nên đưa ra một câu trả lời đúng. Nếu tất cả các điểm của đa giác nằm trong một điểm khác và nếu các đường thẳng của chúng không giao nhau, thì poly đầu tiên hoàn toàn nằm trong điểm khác.
Hackworth

Đúng, nó trả về dương tính giả, nó cũng cần phải tính đến các giao điểm cạnh.
teodron

Đây có vẻ là câu trả lời đúng. Tôi nghĩ không cần thiết phải kiểm tra điều kiện vòng lặp thứ hai.
dùng960567

Điều này không hoạt động cho các giao điểm cuối hoặc nếu các cạnh trùng nhau.
Brandon Kohn

2

Hãy thử làm một giao điểm đường với mỗi đường màu đỏ. Trong mã giả:

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

Tuy nhiên, như bạn có thể thấy, giải pháp này sẽ chậm hơn khi bạn thêm nhiều đa giác để kiểm tra. Một giải pháp khác có thể là:

  • Kết xuất đa giác container thành bộ đệm pixel với màu trắng.
  • Kết xuất một đa giác con vào một bộ đệm pixel khác với màu trắng.
  • Mặt nạ bộ đệm chứa trên bộ đệm đa giác bằng mặt nạ XOR.
  • Đếm số lượng pixel trắng; nếu nó lớn hơn 0 thì đa giác con không được chứa trong container.

Giải pháp này rất nhanh, nhưng nó phụ thuộc vào việc triển khai của bạn (và những gì bạn muốn làm với kết quả kiểm tra của bạn) giải pháp nào phù hợp nhất với bạn.


1
Các giao lộ đường sẽ không đủ để phát hiện các đa giác chứa đầy đủ.
Kylotan

1
Câu hỏi: nếu đa giác hoàn toàn rời rạc, không có cạnh nào sẽ giao nhau. Nó sẽ làm việc trong trường hợp này? Cách tiếp cận thứ hai, dựa trên đồ họa nên hoạt động thực sự!
teodron
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.