Hier ist ein paar vorgeschlagene Pseudo-Code. Einfache Version zuerst, robustere Version später (nur um das Prinzip von den Neunen zu trennen). Einfache Version:
// 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);
}
Hinzufügen Jetzt einige Robustheit:
[Edit: Hinzugefügt explizite Berücksichtigung für den Fall eines einzelnen Scheitelpunkt auf der Ebene]
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
}
Hoffentlich eine Idee gibt, aber es sind noch einige potenzielle Optimierungen. Wenn Sie beispielsweise diese Schnittpunkte für jedes Dreieck in einem großen Netz berechnen, können Sie DistanceFromPlane einmal pro Vertex berechnen und zwischenspeichern und für jede Kante abrufen, an der der Vertex teilnimmt. Es kann auch ein fortgeschritteneres Caching geben. abhängig von Ihrem Szenario und der Datendarstellung.
danke sehr, das erklärt es wunderbar – Martin
Ich denke, dass sollte p1 + t * sein (p2 - p1); anstatt was du hast? – Martin
danke! Ein weiterer Tippfehler wurde behoben. –