Sẽ không có một câu trả lời viên đạn ma thuật cho câu hỏi này; đến một lúc nào đó bạn sẽ phải mút nó và xem xét tất cả các trường hợp. Tôi đã từng phải tính toán giao điểm của một hình tam giác và một hình tròn ... thật kinh khủng. Vì hình dạng 3D của bạn có các đối xứng nhất định (như thực tế rằng nó luôn luôn là hình lăng trụ tam giác) giúp thu hẹp rất nhiều khả năng.
- Tìm mặt nào của mặt phẳng mỗi điểm nằm.
- Nếu tất cả các điểm là ở một bên, thực hiện.
- Nếu một điểm được ngăn cách với 5 điểm còn lại bởi mặt phẳng, giao điểm là một hình tam giác. Có lẽ, bạn có thông tin kết nối để cho bạn biết những mặt nào là sự cố trên đỉnh và bạn có thể tính 3 đường do giao tuyến của mặt phẳng và sau đó là tam giác giao nhau. Tốt nhất làm tất cả điều này trong một tham số hóa của mặt phẳng giao nhau.
- Hai điểm được tách ra, hoặc cả hai đều nằm trên cùng một mặt tam giác của lăng kính hoặc chúng là hai điểm tương ứng trên các mặt tam giác đối diện. Trong cả hai trường hợp, giao điểm là một hình tứ giác.
- Đối với ba điểm, tất cả chúng có thể là cùng một khuôn mặt hình tam giác hoặc chỉ có hai trên đó. Bạn có hai trường hợp ở đây, cho một hình tam giác hoặc hình lục giác kết quả.
Đó thực sự là những trường hợp cấp cao duy nhất, rõ ràng có những mức giảm đối xứng bạn cần áp dụng (trong trường hợp 5, trường hợp một điểm tương đương với trường hợp 2 điểm trên khía cạnh tam giác khác).
Một gợi ý của tôi cho bạn là chọn một đại diện mạnh mẽ cho các hình dạng của bạn và sử dụng các vị từ mạnh mẽ để thực hiện các bài kiểm tra hình học. Đối với mặt phẳng, nó được biểu diễn tốt nhất dưới dạng một điểm trên mặt phẳng và là một vectơ bình thường đơn vị. Lăng kính được thể hiện bằng cách xác định một cơ sở trực giao (bộ ba) với một trục thẳng hàng với hướng đùn của lăng kính. Đặt một đỉnh ở gốc, hai đỉnh còn lại trên mặt tam giác được biểu diễn theo tọa độ uv của bộ ba, và sau đó bạn chỉ cần lưu trữ chiều cao của nó và bù toàn cầu của đỉnh cơ sở. Về cơ bản, tôi đang suy nghĩ
struct plane{
double p[3]; // point on plane
double n[3]; // unit normal vector to plane
};
struct TriPrism{
double basis[9]; // 3x3 orthogonal matrix of local coordinate frame (det = +1)
// Stored columnwise, first two vectors are in the plane of the triangular face)
// Last vector is parallel to extrusion direction, call the set [u, v, w]
double base[3]; // global coordinates of base vertex (where the basis vectors are "rooted")
double buv[2]; // the uv-coordinates of the second point on the triangular face
double cuv[2]; // third point on triangular face
// Assume that the "bottom" triangular face is formed by vertices (a,b,c)
// with base being a, and (b-a) cross (c-a) directed along vector w (instead of against)
double h; // height of prism ("top" triangular face is h*w offset from the "bottom" face)
};
Đại diện này là mạnh mẽ để di chuyển lăng kính xung quanh và nên duy trì độ chính xác tương đối cao cho tất cả các trường hợp ngoại trừ bệnh lý nhất.
Đối với các vị từ mạnh, tôi đánh giá cao các vị từ mạnh của Shewchuk
giả sử bạn sử dụng các số dấu phẩy động thông thường. Bạn sẽ chủ yếu sử dụng orient3d
.
Về mặt đại diện cho đa giác đầu ra cuối cùng, chọn một tham số phù hợp của mặt phẳng. Theo tôi, sự lựa chọn tốt nhất là trước tiên chọn một cơ sở trực giao được đặt trong mặt phẳng, được xác định bởi Gram-Schmidt trên vectơ bình thường của mặt phẳng ( xem geom_maketriad3d tại đây ). Sau đó, hãy để gốc của mặt phẳng tham số 2D đó là hình chiếu của điểm cơ sở lăng kính vào mặt phẳng. Điều này đảm bảo tham số hóa của bạn thực sự bắt nguồn từ gần nơi đa giác kết quả, để đảm bảo sử dụng hiệu quả các bit của các số dấu phẩy động liên quan. Thực hiện tất cả các tính toán còn lại bằng cách sử dụng tham số này nếu có thể.
Nói chung, tính toán hình học đầy rủi ro do những cân nhắc về số ngớ ngẩn này (một lỗi nhỏ với một đỉnh gần mặt phẳng trong trường hợp 5 ở trên có thể thay đổi mạnh mẽ kết quả từ 4 gon thành 6 gon). Tôi đề nghị bạn xử lý một vài trường hợp tại một thời điểm và cố gắng hình dung kết quả. Tôi có một chương trình xem khá đơn giản ở đây , với một loại khả năng ngôn ngữ nhập giống như mô tả. Bạn có thể đổ các mặt của lăng kính và vẽ mặt phẳng và cũng vẽ các đa giác kết quả và kiểm tra trực quan chúng để xem chúng có đúng không.
Phụ lục : Tôi quên rằng ban đầu bạn muốn khu vực của đa giác giao nhau. Nó là tầm thường, nhưng trong trường hợp bạn không biết, một khi bạn có tập hợp các đường xác định các cạnh của đa giác trong mặt phẳng cắt, bạn phải chuyển đổi nó thành biểu diễn đỉnh. Vì bạn đã xây dựng các giao điểm từ các giao điểm giữa mặt phẳng và mặt phẳng, nên bạn có thể theo dõi thứ tự của các đường và do đó thứ tự của các cạnh đi xung quanh đa giác. Bạn chỉ cần tính toán giao điểm của các cặp liên tiếp của các đường thẳng này để có được các đỉnh. Khi bạn đã có các đỉnh, việc lấy diện tích là một vấn đề đơn giản ( xem ví dụ geom_polygon_area2d tại đây ). Nếu bạn làm việc hoàn toàn trong tọa độ uv của mặt phẳng cắt, thì bạn có thể đưa chúng trực tiếp đến một chức năng như vậy để có được khu vực.
Tôi nên nói thêm rằng có một cách tiếp cận ngu ngốc rõ ràng, đó là chọn một vùng lớn phù hợp trong mặt phẳng cắt, và lấy mẫu ngẫu nhiên các điểm và kiểm tra xem chúng có nằm trong lăng kính không (vì nó rẻ, vì nó lồi). Sau đó, bạn có thể tính diện tích theo tỷ lệ điểm bên trong so với tổng số điểm, nhân với diện tích của vùng lấy mẫu. Nếu bạn thực sự không quan tâm đến độ chính xác, thì điều này có thể sẽ nhanh hơn, nhưng nếu không, phương pháp phân tích không nên chậm hơn nhiều, mặc dù độ phức tạp của nó rất phức tạp.