2010-06-29 39 views
17

Tôi có một hình tam giác đơn và mặt phẳng (trong không gian 3 chiều), Làm cách nào tôi tính toán đoạn đường mà hai đường chéo, nếu không có đường giao nhau thì tôi cần phát hiện trường hợp.Xác định giao điểm của tam giác và mặt phẳng

Kết quả cuối cùng tôi đang tìm kiếm là hai vectơ 3 chiều, xác định điểm bắt đầu và điểm kết thúc của đoạn đường.

Để giúp bạn một chút, tôi đã tính toán tia giao nhau giữa mặt phẳng của mặt và mặt phẳng, tôi chỉ cần tìm các điểm cuối để cắt tia đó thành một đoạn thẳng.

Đối với những người thích những thứ đọc trong mã:

Face face;  //a face, defined by 3 points 
Plane plane;  //a plane, defined by a normal vector and a distance 
Ray intersection; //a ray, defined by a point and a direction, initialised to the intersection of the face plane and the face 

Segment s = CalculateSegment(face, plane, intersection); //this method needs defining 

Trả lời

16

Dưới đây là một số mã giả được đề xuất. Phiên bản đơn giản đầu tiên, phiên bản mạnh mẽ hơn sau này (chỉ để giúp tách nguyên tắc khỏi các vết thương). phiên bản đơn giản:

// Assume the plane is given as the equation dot(N,X) + d = 0, where N is a (not 
// neccessarily normalized) plane normal, and d is a scalar. Any way the plane is given - 
// DistFromPlane should just let the input vector into the plane equation. 

vector3d planeN; 
float planeD; 

float DistFromPlane(vector3d P) 
{ 
// if N is not normalized this is *not* really the distance, 
// but the computations work just the same. 
    return dot(planeN,P) + planeD; 
} 

bool GetSegmentPlaneIntersection(vector3d P1, vector3d P2, vector3d& outP) 
{ 
    float d1 = DistFromPlane(P1), 
     d2 = DistFromPlane(P2); 

    if (d1*d2 > 0) // points on the same side of plane 
    return false; 

    float t = d1/(d1 - d2); // 'time' of intersection point on the segment 
    outP = P1 + t * (P2 - P1); 

    return true; 
} 

void TrianglePlaneIntersection(vector3d triA, vector3d triB, vector3d triC, 
           vector3dArray& outSegTips) 
{ 
    vector3d IntersectionPoint; 
    if(GetSegmentPlaneIntersection(triA, triB, IntersectionPoint)) 
    outSegTips.Add(IntersectionPoint); 

    if(GetSegmentPlaneIntersection(triB, triC, IntersectionPoint)) 
    outSegTips.Add(IntersectionPoint); 

    if(GetSegmentPlaneIntersection(triC, triA, IntersectionPoint)) 
    outSegTips.Add(IntersectionPoint); 
} 

Bây giờ thêm một số mạnh mẽ:
[Chỉnh sửa: Thêm xem xét rõ ràng đối với trường hợp của một đỉnh duy nhất trên máy bay]

vector3d planeN; 
float planeD; 

float DistFromPlane(vector3d P) 
{ 
    return dot(planeN,P) + planeD; 
} 

void GetSegmentPlaneIntersection(vector3d P1, vector3d P2, vector3dArray& outSegTips) 
{ 
    float d1 = DistFromPlane(P1), 
     d2 = DistFromPlane(P2); 

    bool bP1OnPlane = (abs(d1) < eps), 
     bP2OnPlane = (abs(d2) < eps); 

    if (bP1OnPlane) 
    outSegTips.Add(P1); 

    if (bP2OnPlane) 
    outSegTips.Add(P2); 

    if (bP1OnPlane && bP2OnPlane) 
    return; 

    if (d1*d2 > eps) // points on the same side of plane 
    return; 

    float t = d1/(d1 - d2); // 'time' of intersection point on the segment 
    outSegTips.Add(P1 + t * (P2 - P1)); 
} 

void TrianglePlaneIntersection(vector3d triA, vector3d triB, vector3d triC, 
           vector3dArray& outSegTips) 
{ 
    GetSegmentPlaneIntersection(triA, triB, outSegTips)); 
    GetSegmentPlaneIntersection(triB, triC, outSegTips)); 
    GetSegmentPlaneIntersection(triC, triA, outSegTips)); 

    RemoveDuplicates(outSegTips); // not listed here - obvious functionality 
} 

Hy vọng rằng đưa ra một ý tưởng, nhưng có vẫn còn một vài tối ưu tiềm năng. Ví dụ, nếu bạn tính toán các giao điểm này cho mỗi tam giác trong một lưới lớn, bạn có thể tính toán và nhớ cache DistanceFromPlane một lần trên mỗi đỉnh, và chỉ lấy nó cho mọi cạnh đỉnh tham gia. tùy thuộc vào kịch bản và biểu diễn dữ liệu của bạn.

+0

thankyou rất nhiều, điều này giải thích nó tuyệt vời – Martin

+0

Tôi nghĩ rằng nên được p1 + t * (p2 - p1); thay vì những gì bạn có? – Martin

+0

cảm ơn! một lỗi đánh máy khác cũng được sửa. –

1

Nó phụ thuộc một chút về những gì thư viện mà bạn có. Tôi đã tạo ra thư viện hình học của riêng tôi mà có thể tính toán giao điểm của một đường thẳng với một mặt phẳng. Trong trường hợp này tính toán ba điểm giao nhau của ba cạnh của tam giác và sau đó tính toán điểm nào trong số chúng nằm giữa các đỉnh. Điều này có thể là 0 (không có giao lộ), hoặc 2 là trường hợp bạn muốn. (Có những trường hợp đặc biệt mà hai điểm trùng hợp nhau - một điểm của tam giác).

2

Cắm 3 điểm vào phương trình phẳng (được xác định bởi 4 tham số bạn liệt kê a, b, c, d) và xác định cặp nào nằm ở hai phía đối diện của mặt phẳng.

Với phương trình mặt phẳng:

 
Ax + By + Cz + D = 0 

trong đó A, B, C là bình thường (đơn vị chiều dài) và D là khoảng cách đến nguồn gốc IIRC, bạn cắm vào điểm (x, y, z) và xem kết quả này là dương hay âm. Nó sẽ bằng không cho các điểm trên mặt phẳng, và biển báo sẽ cho bạn biết điểm bên nào đang bật khi kết quả không bằng 0. Vì vậy, hãy chọn các cặp điểm trên các cạnh đối diện (sẽ có tối đa 2) và tính toán giao điểm của 2 phân đoạn đó với mặt phẳng bằng cách sử dụng công thức giao cắt tia/mặt phẳng chuẩn mà tôi thoát ra ngay bây giờ. Đó sẽ là 2 điểm tạo thành phân đoạn bạn tìm kiếm.

EDIT Nghĩ về nó, các giá trị bạn nhận được từ việc cắm điểm vào phương trình mặt phẳng sẽ hữu ích cho việc nội suy giữa các cặp điểm để có giao điểm của phân đoạn với mặt phẳng.

Len Fn = A xn + B yn + C * zn + D là kết quả của việc cắm vào điểm n. Giả sử F1 = -4 và F2 = 8. Vì vậy, điểm P1 và P2 nằm trên các cạnh đối diện của mặt phẳng. Chúng ta cũng sẽ có P = P1 * 2/3 + P2 * 1/3 là điểm giao nhau của đoạn từ P1 đến P2 với mặt phẳng. Việc khái quát hóa điều này thành một công thức thích hợp được để lại như là một phép trừ tà.

+0

Bình thường không phải là đơn vị chiều dài (mặc dù nếu nó không phải là đơn vị chiều dài, D sẽ không đại diện cho khoảng cách). Phần còn lại là chính xác. Ngoài ra bạn quên đề cập đến tình hình khi tất cả các điểm nằm trên một mặt của máy bay và không có giao lộ. – SigTerm

+0

Có, tôi hơi cẩu thả - những gì bạn nói về bình thường và phương trình là chính xác. Ngoài ra 1/3 và 2/3 đã được đảo ngược (chỉnh sửa) giá trị nhỏ hơn là giá trị gần với mặt phẳng và tăng trọng gần hơn với 1. Khi tất cả các điểm ở một bên, tất cả Fn sẽ có cùng dấu và không có giao lộ . – phkahler

1

Tìm giao điểm của từng đoạn đường bao quanh hình tam giác với mặt phẳng. Merge điểm giống hệt nhau, sau đó

  • nếu 0 nút giao thông tồn tại, không có ngã tư
  • nếu 1 ngã tư tồn tại (tức là bạn đã tìm thấy hai nhưng họ giống hệt nhau để trong vòng khoan dung), bạn có một điểm của tam giác chỉ cần chạm vào máy bay
  • nếu 2 điểm sau đó phân khúc ranh giới giữa chúng là ngã tư

bước tiếp theo, tìm SO cho dòng phân đoạn để thuật toán giao máy bay (hoặc chỉ cần sử dụng một trong những cung cấp bởi khuôn khổ của bạn) ...

Các vấn đề liên quan