Làm cách nào để kiểm tra xem các điểm có nằm trong đa giác không?


7

Tôi có các điểm 2D, ranh giới mô tả một đa giác. Các điểm nằm ở vị trí nguyên (không có phân số có thể).

Bây giờ tôi muốn xây dựng một điều tra viên trong C # trả về tất cả các điểm nằm trong đa giác. Việc thực hiện điều tra không phải là vấn đề, nhưng làm thế nào để tôi đạt được tất cả các điểm một cách hiệu quả? Đa giác có thể khá lớn.


Là đa giác luôn luôn lồi hoặc có thể không lồi?
Regent Regya

Câu hỏi hay, thực sự không biết, nhưng .... đa giác đại diện cho các khu vực, được tạo ngẫu nhiên. Nếu lồi sẽ có lợi trong một thuật toán đơn giản hơn, tôi có thể sống với nó, tôi đoán
Marco

Có ít nhất 2 giải pháp khác nhau được trả lời, nhưng tôi muốn thêm một bình luận. Nếu bạn gặp vấn đề như "có bao nhiêu điểm có tọa độ nguyên nằm trong đa giác" thì bạn có thể giải quyết nó bằng cách chia đa giác thành hình tam giác vuông và hình chữ nhật. Trong trường hợp này, bạn có thể dễ dàng tính số điểm (sử dụng công thức tính diện tích) mà không cần lặp lại. Thuật toán này phụ thuộc vào số lượng đỉnh đa giác, không phụ thuộc vào số điểm bên trong đa giác. Nó hoạt động với các đa giác lồi và không lồi, nhưng trong trường hợp không lồi, số điểm trong một số tam giác nên âm.
Regent Regya

Ok, nhưng tôi cần tọa độ của các điểm. Vì vậy, trên thực tế đa giác nằm trong thuật ngữ OO là một thùng chứa và 'điểm' bên trong là các ô. Các tế bào là con của container (trong trường hợp này là đa giác). Nhưng với câu trả lời tôi có thể tiếp
tục..thx

Câu trả lời:


7

Những gì bạn đang tìm kiếm là một giải pháp cho vấn đề "điểm đa giác". Nó được mô tả trong Wikipedia ở đây :


          Hình ảnh Wikipedia


Bạn có thể tìm thấy mã C theo các liên kết đến Hình học tính toán trong C hoặc tại nhiều vị trí khác được tìm thấy bằng cách tìm kiếm mã "điểm đa giác".


Joseph, tôi không tìm kiếm nếu một điểm nằm trong đa giác, tôi muốn tất cả các điểm nằm trong đa giác. Câu hỏi của tôi là một thuật toán hiệu quả sẽ trông như thế nào để giải quyết vấn đề này
Marco

2
Đối với mỗi điểm, kiểm tra xem nó có nằm trong đa giác không. Không có phương pháp nào đơn giản hơn, trừ khi điểm của bạn được sắp xếp theo kiểu không hợp lý mà bạn không chỉ định.
Joseph O'Rourke

2
@ Hawk66, bạn có thể cải thiện giải pháp này cho mục đích của mình. Thực hiện kiểm tra cho mỗi đa giác tọa độ Y có và lặp lại theo điểm khi số lượng các đường giao nhau là số lẻ (phương tiện lẻ bên trong).
Regent Regya

Ok, thx để làm rõ
Marco

2
Có nhiều thuật toán point-in-poly được liệt kê ở đây trong C. tog.acm.org/resource/GraphicsGems/gemsiv/ptpoly_haines/ Lỗi
Syntac_

9

Bạn sẽ cần xử lý tất cả các điểm ít nhất một lần vì vậy nếu kiểm tra này chỉ được thực hiện một lần thì bạn không thể làm gì nhiều để tăng tốc độ kiểm tra ngoài việc bắt buộc sử dụng song song.

Nếu thử nghiệm sẽ được chạy nhiều lần, có nhiều cách để tính toán trước các bảng để trợ giúp, chẳng hạn như một lưới các ô được đánh dấu là [chắc chắn bên trong ( màu xanh lá cây trong hình ảnh), bên ngoài ( màu đỏ ) và có thể ( màu xanh )], chỉ các điểm rơi trong các ô màu xanh cần được kiểm tra đối với đa giác.

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

Nhưng nếu nó chỉ chạy một lần chỉ với một vài điểm so với lưới hoặc quá nhiều ô "có thể" thì việc xây dựng bảng này có thể sẽ mất nhiều thời gian hơn là chỉ kiểm tra điểm của bạn.

Bạn cần có nhiều điểm hơn các ô (lưới độ phân giải thấp) để điều này có thể tạo ra "lợi nhuận" và hầu hết các ô phải kết thúc dưới dạng xác định bên trong hoặc bên ngoài (lưới độ phân giải cao), vì vậy, tìm sự cân bằng giúp tăng tốc mọi thứ giữa các ô đó hai yếu tố có thể khó khăn.

Thật dễ dàng và nhất quán hơn về mặt lợi ích khi chỉ cần phân chia số điểm giữa nhiều luồng và thực hiện một bài kiểm tra giao nhau chẵn lẻ. Việc xử lý GPGPU như OpenCL có thể giúp bạn tăng tốc dễ dàng và rất lớn cho loại thử nghiệm này chỉ bằng cách sử dụng một số lượng lớn lõi.


Nếu các điểm đại diện cho các góc của hình vuông của lưới, có vẻ như có thể có các điểm bên trong ngôi sao của bạn nhưng không được mô tả bằng màu xanh lá cây. Chúng sẽ là các góc của hình vuông, vì vậy không phải tất cả bốn điểm trên mỗi hình vuông sẽ ở bên trong ngôi sao. Giải pháp cuối cùng có thể yêu cầu độ lệch nửa pixel hoặc một số như vậy, sao cho bất kỳ hình vuông nào có tâm nằm trong đa giác đều được tô màu theo một cách nhất định.
Seth Battin

1
@SethBattin Theo hiểu biết của tôi, các hình khối trong sơ đồ KHÔNG phải là hình vuông đơn vị, mà là các vùng lớn hơn. Tất cả các ô vuông đơn vị (hoặc thậm chí tọa độ điểm nổi) trong mỗi khối màu xanh lá cây đều nằm trong đa giác, tất cả các ô vuông đơn vị trong một khối màu đỏ đều ở bên ngoài và chỉ các ô vuông đơn vị trong một khối màu xanh yêu cầu kiểm tra đầy đủ. Thách thức trong phương pháp này là tìm ra sự cân bằng phù hợp giữa tốc độ đánh giá (ở kích thước vùng nhỏ) và hiệu quả bộ nhớ và tốc độ khởi tạo (ở kích thước vùng lớn) cho trường hợp sử dụng cụ thể.
DeveloperInDevelopment

2

Để phát hiện điểm thời tiết A ở trên hoặc dưới dòng L, bạn phải biến dòng L thành hàm f (x) = y = ax + b bằng cách sử dụng hai điểm đại diện cho dòng là x = P1.xy = P1.y và x = P2 .xx = P2.x bao gồm chúng vào hệ thống. Một khi bạn đã tính hàm f (x), bạn chỉ cần kiểm tra nếu f (Ax)> <= Ay. Nếu f (Ax)> Ay thì dòng L nằm trên điểm A. If = 0 thì nó nằm trên dòng khác bên dưới nó. Nó có thể trông hơi phức tạp, nhưng hầu hết các tính toán đó là tức thời và chỉ có thể được tính một lần. Khi bạn lưu trữ các mảng V, L, P trong lớp đa giác đại diện. y thì dòng L nằm trên điểm A. If = 0 thì nó nằm trên dòng khác bên dưới nó. Nó có thể trông hơi phức tạp, nhưng hầu hết các tính toán đó là tức thời và chỉ có thể được tính một lần. Khi bạn lưu trữ các mảng V, L, P trong lớp đa giác đại diện. y thì dòng L nằm trên điểm A. If = 0 thì nó nằm trên dòng khác bên dưới nó. Nó có thể trông hơi phức tạp, nhưng hầu hết các tính toán đó là tức thời và chỉ có thể được tính một lần. Khi bạn lưu trữ các mảng V, L, P trong lớp đa giác đại diện.

PS: Nếu dòng L có điểm P1 và P2 là như vậy thì P1.x = P2.x thì bạn không thể tạo hàm dựa trên f (x) = ax + b, bạn chỉ cần kiểm tra xem điểm A (mà bạn đang so sánh nếu dòng dưới hoặc trên của nó L) A.xP1x. của nó ở trên.of nếu Ax = P1.x thì nó trên đó


1

Bạn có thể coi nó như một vấn đề truyền tải đồ thị. Nếu bạn coi các điểm liền kề là 'con' của nhau và thêm từng điểm con của các điểm biên của bạn vào danh sách các nút mở (ví dụ: các nút không được chú ý), thì điều tra viên của bạn có thể khám phá danh sách này.

Trong trường hợp bạn không quen thuộc với các thuật toán tìm kiếm, điều này có thể sẽ trông giống như:
Đối với mỗi điểm; thêm điểm vào một tập hợp các nút đóng (ví dụ: đã truy cập). Nếu điểm nằm trong đa giác, hãy thêm nó vào liệt kê của bạn và thêm điểm con vào danh sách các nút mở của bạn. Tiếp tục cho đến khi danh sách các nút mở của bạn trống. Ngoài ra, chỉ thêm các nút vào danh sách mở của bạn nếu chúng chưa có trong danh sách đã đóng của bạn.

Một vài lưu ý:

  • Tôi sẽ lập luận rằng phương pháp này thể hiệu quả hơn là chỉ đơn giản là "vẽ các đường" thông qua các hình dạng của bạn. Đáng chú ý; nếu bất kỳ đa giác nào của bạn bị lõm, các đường vẽ có thể không phát hiện ra một số phần của hình mà không kiểm tra số lượng lớn các điểm không nằm trong hình dạng. Tuy nhiên, bạn sẽ kết thúc với chi phí bộ nhớ lớn hơn nhiều so với sử dụng các dòng.
  • Nếu bạn không cần mọi điểm ngay lập tức, phương pháp này có thể cho phép bạn tạo điểm tiếp theo theo yêu cầu.
  • Bạn có thể cải thiện hiệu suất của giao dịch nếu vấn đề của bạn là phù hợp với việc sử dụng phương pháp phỏng đoán. Điều này có liên quan nhất nếu bạn đang tìm kiếm một điểm cụ thể (hoặc nhóm điểm) thỏa mãn một số tài sản.

1

Có một cái nhìn tại đây. Nó hoạt động thông qua một số sơ đồ rất rõ ràng.

http://www.mathopenref.com/coordpolygonarea2.html

Họ chỉ là tính diện tích và bạn đang liệt kê điểm. Tuy nhiên bạn có thể thích nghi với những ý tưởng này. Hãy xem xét kỹ 'Trường hợp phức tạp hơn' và cách các đường nằm ngang chia đa giác thành một tập hợp các hình thang (nếu bạn nhận ra một hình tam giác là hình thang suy biến có cạnh dài bằng 0).

Nếu đa giác của bạn (có khả năng) lõm, bạn cần loại bỏ một số hình thang dựa trên hướng di chuyển của quy tắc Y (n) -Y (n + 1) được đề cập trong văn bản.

Vì vậy, bây giờ bạn đã giảm việc liệt kê các điểm trong một đa giác thành liệt kê các điểm trong một loạt các hình thang. Điều đó không nên quá khó, đặc biệt là các hình thang được định hướng độc đáo là "bị kẹt" hai đường thẳng song song với trục X. Có lẽ dễ nhất để làm điều đó trong quá trình quét raster vì vậy bạn chỉ phải tính bắt đầu X và kết thúc X của mỗi hàng raster.

Cấu trúc dữ liệu của bạn có thể trông giống như một danh sách các đa giác, một chỉ mục cho biết bạn đang ở trong đa giác nào, x và y phối hợp với bạn và chỉ mục cuối của hàng raster bạn đang ở.

Tôi cho rằng bạn không quan tâm đến thứ tự bạn liệt kê!

Sự phức tạp hơn nữa sẽ xảy ra nếu 'đa giác' của bạn bao gồm các hình dạng rời rạc (nghĩa là thực sự nhiều hơn một đa giác hoặc có thể chứa các 'lỗ' đa giác.

Độ phức tạp của việc thu được các hình thang là khá thấp nhưng việc lặp lại qua một số lượng lớn các điểm có thể khá chậm. Tôi không biết bạn đang làm điều này để làm gì nhưng như được chỉ ra bởi Stephane Hockenhull trên một trọng lượng thông thường để làm cho nó dễ dàng hơn là sử dụng một xấp xỉ thô.

Điều đó có nghĩa là thực sự quét theo các bước của (nói) 5 và (nếu thuật toán của bạn có thể sửa chữa được) coi điểm trung tâm của ô 5 * 5 'là đại diện nào đó.

Tôi hy vọng bạn không tìm kiếm một câu trả lời dễ dàng? Tôi muốn thấy một số mã cho việc này!

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.