Làm thế nào tôi có thể thêm và trừ các đa giác lồi?


12

Tôi có hai đa giác lồi 2D chồng chéo lên nhau . Tôi đang tìm kiếm một thuật toán để trừthêm chúng. Kết quả phải là một đa giác lõm đơn hoặc (thậm chí tốt hơn) một tập hợp các hình lồi lớn nhất tạo thành kết quả lõm (ví dụ: hình tam giác).

nhập mô tả hình ảnh ở đây

( Bên trái: . Các ban đầu chồng chéo đa giác Trung: . Kết quả là đa giác lõm sau khi thêm phải: . Một tập hợp các đa giác lồi hình thành kết quả lõm Ở đây nó sẽ được tốt hơn để có được đa giác lồi lớn hơn một tam giác vì lý do hiệu suất Một phép trừ của. hai đa giác chồng chéo sẽ dẫn đến cùng một hình ảnh như bên trái nhưng với vùng chồng lấp không phải là một phần của đa giác kết quả.)

Tôi có thể làm cái này như thế nào?


Có phải chúng ta đang nói về 2D ở đây? bởi vì trong 3D kết hợp đa giác không thực sự có ý nghĩa nhiều.
Concept3d

Vâng, xin lỗi, tôi đang nói về 2D! Mặc dù tôi không hiểu tại sao nó không có ý nghĩa trong 3D hơn là 2D.
Sebastian Barth

2
thêm hai đa giác trong 3D, nếu chúng phẳng, sẽ không có ý nghĩa gì trừ khi chúng ở trên cùng một mặt phẳng, nếu chúng có thể tích (chất rắn) thì đó là một câu chuyện khác.
Concept3d

Ok, tôi đã hiểu rồi. Tôi đã không nghĩ về đồ họa, nhưng các đối tượng va chạm. Cảm ơn bạn đã làm rõ.
Sebastian Barth

Ngoài ra, tìm tất cả các điểm chúng giao nhau và thêm các đỉnh vào một tập hợp. Các thiết lập là quan trọng để ngăn chặn chồng chéo. Sau đó, chỉ cần thêm mọi đỉnh khác từ hai hình dạng khác vào tập hợp. Tập hợp này chứa tất cả các đỉnh của hình dạng phụ gia.
Vaughan Hilts

Câu trả lời:


9

TL; DR Bạn cần triển khai các thao tác boolean bằng cây BSP.

Chà, có vẻ như chúng ta đang nói về Hình học rắn xây dựng ở đây. Tôi đã triển khai CSG ở cấp độ thương mại để tôi biết một vài điều về nó.

Bài báo kinh điển về CSG có tên là Hợp nhất các cây hoạt động của cây đa năng Yields , thành thật mà nói, quá nhiều để giải thích ở đây, nhưng nói ngắn gọn thuật toán xử lý các đa giác nằm trên cùng một mặt phẳng như phân vùng không gian nhị phân, về cơ bản là xây dựng một cây BSP từ mỗi lưới đa giác. Bước thứ hai là hợp nhất các cây BSP đó; bạn chỉ cần lấy một cây và chèn nó vào cây kia. Thuật toán sau đó tiến hành giải thích làm thế nào để đối phó với từng nút lá để phân chia và trừ các nút, các nút không cần thiết trong hình dạng cuối cùng sẽ bị loại bỏ, các nút khác sẽ được cung cấp cho cha mẹ thích hợp.

Nhưng chờ đã! Bài báo đó về cơ bản là nói về các lưới đa giác và các mặt phẳng 3D, KHÔNG?

Thuật toán có thể được khái quát thành bất kỳ chiều nào, vì vậy trong trường hợp 2D của bạn, thật dễ dàng sử dụng các phân đoạn dòng thay vì mặt phẳng như các phân vùng nhị phân. Vì vậy, mỗi đa giác sẽ được chuyển đổi thành cây BSP hơn hai cây sẽ được hợp nhất. Cuối cùng, bạn đi qua cây kết quả để tạo đa giác cuối cùng,

Lưu ý rằng thuật toán này và CSG nói chung không liên quan trực tiếp đến kết xuất và mặt lưới và không thực sự hiển thị sẵn sàng, vì vậy bạn cần trích xuất các mặt của các cây BSP cuối cùng. Tôi cũng tìm thấy tia truy tìm một cách tiếp cận dễ dàng hơn để hiển thị kết quả CSG, bạn chỉ cần các tia đi ngang qua cây thay vì trích xuất và thực sự tách các mặt (hãy nhớ rằng chúng ta chỉ xử lý các phân vùng nhị phân).

Về độ mạnh của số. Thật tốt khi lưu ý rằng có hai loại tính toán hình học,

  • Những người dựa trên xây dựng, bạn xây dựng một hình dạng dựa trên kết quả của một hoạt động trước đó. Ví dụ y = sqrt(x)và sau đó sử dụng ytrong một hoạt động mới. Đây được gọi là xây dựng; vấn đề là lỗi số sẽ tích lũy nhanh chóng.
  • Ngoài ra, có các hoạt động sử dụng các vị từ thay vào đó, về cơ bản thay vì sử dụng xây dựng, bạn chỉ cần hỏi liệu một điều kiện có đúng / sai và sử dụng cùng một giá trị trong các hoạt động khác nhau. Các xét nghiệm cổ điển bao gồm bao vây và thử nghiệm định hướng; điều này cũng nghi ngờ với các lỗi số đặc biệt là nếu bạn sử dụng độ chính xác đơn hoặc kép nhưng thường sẽ cho kết quả tốt hơn nhiều. các giải pháp khác thay đổi về tốc độ và độ chính xác tồn tại. Dưới đây là một trong những bài báo gần đây tránh xây dựng bằng cách sử dụng hình học dựa trên mặt phẳng để cho kết quả chính xác. Tôi cũng sẽ trích dẫn từ bài báo:

Khái niệm biểu diễn trên mặt phẳng của các lưới đa giác được mô tả đầu tiên bởi Sugihara và Iri [SI89]. Kiểu biểu diễn này cung cấp một lợi thế quan trọng khi thực hiện các nhiệm vụ liên quan đến việc thay đổi cấu trúc liên kết của vật rắn được biểu thị bằng các mắt lưới như đánh giá biểu thức Boolean: không có thông tin hình học sơ cấp mới nào được tạo ra để thu được khối đa diện kết quả

nhập mô tả hình ảnh ở đây

Và cuối cùng tôi muốn thêm vào, nếu bạn muốn bắt đầu triển khai CSG BSP của mình, tôi khuyên bạn nên bắt đầu trên BSP Faqs .


Tuyệt vời, nhưng phản trực giác, xem xét rằng một BSP của đa giác lồi hoặc đa diện là một danh sách. Giấy lớn.
3Dave

@DavidLively có, nhưng có thể biến nó thành một cây cân bằng bằng cách chọn mặt phẳng gốc không phải là các mặt. Trên thực tế đây là một phần của thử thách mà họ không nói đến
khái niệm

Ah, điều đó có ý nghĩa. Sắp xếp một BSP lai, sau đó.
3Dave

@DavidLively cũng không thực sự dễ dàng để hiển thị, mặc dù câu hỏi OP là một trường hợp đơn giản, trong trường hợp phức tạp hơn với hình học của hàng triệu đa giác, khi bạn hoàn thành việc xây dựng cây bạn sẽ không hoàn thành.
concept3d

@ concept3d Tôi hy vọng điều này sẽ không quá khó chịu vì đây là câu trả lời 5 năm tuổi, nhưng có hai điều tôi không thực sự hiểu: Khi cố gắng xác định xem một điểm nằm bên trái hay bên phải của mặt phẳng / đường thẳng, Sẽ không dễ dàng hơn khi chỉ xoay toàn bộ vật sao cho mặt phẳng / đường thẳng tương ứng với một mặt phẳng / đường tầm thường, và sau đó chỉ xem xét tọa độ của điểm xoay? Làm thế nào về việc sử dụng thuật toán Sutherland của Hodgman thay vì cây BSP? Âm thanh khá giống với phương pháp này.
John P

1

Đi theo ví dụ của bạn:

Chọn một đỉnh bắt đầu trên đa giác A, và sau đó bắt đầu kiểm tra các cạnh giao nhau theo chiều kim đồng hồ (hoặc ngược chiều kim đồng hồ). Nếu không có giao điểm, hãy thêm đỉnh trước vào đa giác kết quả của bạn. Nếu có một giao điểm, hãy thêm điểm tại đó chúng giao nhau với đa giác kết quả của bạn, sau đó bắt đầu lặp lại trên đa giác B, theo cùng thứ tự quanh co. Làm tương tự, một lần nữa hoán đổi thành đa giác A nếu một giao lộ xảy ra.

Khi bạn đã tích lũy tất cả các đỉnh cho đa giác mới, hãy thực hiện thuật toán tam giác trên nó. Các phương pháp tai cắt rất dễ dàng để thực hiện, nhưng có nhanh hơn tùy chọn trên mạng.

Quan trọng: đảm bảo đỉnh bạn bắt đầu không nằm trong đa giác khác (kiểm tra bài viết này để biết điểm trong các bài kiểm tra đa giác).

Lặp lại trên mỗi cạnh, để kiểm tra giao lộ sẽ là thuật toán O (n ^ 2). Bạn có thể tăng tốc nó bằng cách trước tiên tìm các đỉnh nằm trong đa giác khác, vì các cạnh được liên kết với các đỉnh đó sẽ là các đỉnh giao nhau.


0

Nếu bạn muốn đa giác lõm , chỉ cần chọn cạnh gần nhất giữa hai đa giác đầu vào và thêm hai cạnh mới:

nhập mô tả hình ảnh ở đây

Convex hơi phức tạp hơn một chút:

nhập mô tả hình ảnh ở đây

Một cách tiếp cận được lặp đi lặp lại ở chỗ nó thêm các đỉnh từ đa giác thứ hai vào một, một lần, phát triển đa giác đầu tiên thành một thùng chứa bao gồm mọi thứ.

Về cơ bản:

  • Lặp lại qua các đỉnh của đa giác thứ hai.
  • Đối với mỗi đỉnh V, lặp qua các cạnh của đa giác đầu tiên:
  • Tìm một "phạm vi" các cạnh mà tất cả phải đối mặt với đỉnh
  • lấy cặp đỉnh ngoài xác định phạm vi đó và xóa tất cả các cạnh trong phạm vi kết nối chúng
  • Vẽ hai đoạn mới từ các đỉnh ngoài đó sang đỉnh mới (từ đa giác thứ hai), đảm bảo rằng các cạnh mới phải đối mặt với hướng chính xác.
  • Tiếp tục với đỉnh tiếp theo từ đa giác thứ hai

Đây là sơ đồ minh họa quá trình cho đỉnh đầu tiên:

nhập mô tả hình ảnh ở đây

Phương pháp nhanh hơn là tìm danh sách các cạnh trên mỗi đa giác không đối diện với đa giác khác, loại bỏ mọi thứ khác và kết nối các điểm cuối của các dải dòng còn lại với nhau.

Có lẽ ai đó khác có thể kêu vang với một số lời khuyên trừ.


Điều này dường như chỉ giải quyết một nửa vấn đề (bổ sung). Cũng có thể tốt để chỉ ra cách các thuật toán hoạt động hoặc có thể được tối ưu hóa nếu các đa giác trùng nhau.

Thuật toán mặc nhiên bỏ qua các đỉnh "bên trong" của đa giác đích, cũng bù cho vấn đề trong đó một cạnh từ đa giác thứ hai đi qua đỉnh thứ nhất.
3Dave

Điều đó gần như bằng với pha hợp nhất (điểm 4. của thuật toán vỏ hợp nhất . Trong trường hợp của tôi, đó không phải là một giải pháp chính xác để bao quanh nhiều diện tích hơn sau khi kết hợp các đa giác. Giải pháp chính xác là giữ cả hai đa giác vì chúng không xuất hiện T chồng chéo, cũng không chạm vào.
Sebastian Barth

@luftgewehrindianer Ah - Vâng, điều đó tạo ra sự khác biệt lớn. Có lẽ tôi đã hiểu nhầm câu hỏi. Bạn đang tìm cách thêm các đa giác lại với nhau, mà không cần lo lắng về việc kết quả là lồi hay lõm? Hoặc tạo một bộ lồi dựa trên giao lộ? (Bỏ qua phép trừ trong thời điểm này.)
3Dave

@DavidLively Tưởng tượng hai đa giác lồi có cùng màu và không có đường viền. Khi chúng trùng nhau, nó trông giống như một đa giác lồi hoặc lõm mới. Anh ta cố gắng tìm một hình tam giác của hình dạng kết hợp. Đừng thêm khu vực giữa cả hai đa giác.
danijar
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.