|
|
|
|
Input: a 2D
segment S from point P0 to point P1 |
A C++ implementation intersect2D_SegPoly() is given below.
The 2D computations and algorithm extend to 3D with very few changes. The main difference concerns specifying the polyhedron data structure. We let a polyhedron W be given by a list of n (planar) polygon faces Fi for i=0,n-1. We do not assume any relationship between adjacent faces Fi and Fi+1, such as having a common edge or vertex (like adjacent edges of a polygon). It is just an unstructured list of all the distinct faces. However, to make the algorithm work, we need some extra information about each face, namely:
Each face Fi lies completely in a plane.
Vi = a point in the plane of face Fi (e.g.: a vertex of Fi).
ni = an outward-pointing normal vector to Fi ; that is, a normal vector pointing to the side of Fi that is exterior to the polyhedron W.
This information can be precomputed from any decent data structure for a polyhedron.
Again the 3D line segment S = P0P1 is given by a parametric equation P(t). For the intersection of the extended line segment with the plane of a specific face Fi, consider the following diagram.

This is exactly the same condition as in the 2D case; namely, the intersection point occurs when (P(t)-Vi) · ni = 0 as shown. Again, solving this gives:

at the intersection point Ii = P(ti), and the segment is parallel to the face when the denominator is zero. This condition is treated exactly the same.
Further, since ni is an outward-pointing normal vector to the face plane, we have exactly the same criteria for classifying each ti as entering or leaving; namely:

And again we compute:

Finally, the part of the segment inside the convex polyhedron is the subsegment from P(tE) to P(tL) when 0 £ tE £ tL £ 1. If tL < tE, the segment is completely outside the polygon.
[Haines, 1994] used this same method to compute the intersection of a ray and a 3D polyhedron. He noted that t is entering the polyhedron when the intersection is with a front face plane, and is leaving when it intersects a back face plane. However, except for the different semantics, the dot-product classification criteria are exactly the same. Also, for a positive-extended ray starting at t=0, tL is not bounded above by 1, and is simply the minimum of the ti's that are leaving.
The 3D pseudo-code is almost the same as for 2D polygons, but with the obvious modifications.
|
Input: a 3D
segment S from point P0 to point P1 |
Here is a sample "C++" implementation of this algorithm.
// Copyright 2001, softSurfer (www.softsurfer.com)
// This code may be freely used and modified for any purpose
// providing that this copyright notice is included with it.
// SoftSurfer makes no warranty for this code, and cannot be held
// liable for any real or imagined damage resulting from its use.
// Users of this code must verify correctness for their application.
// Assume that classes are
already given for the objects:
// Point and Vector with
// coordinates {float x, y;}
// operators for:
// == to test
equality
// != to test
inequality
// Point
= Point ± Vector
// Vector =
Point - Point
// Vector =
Vector ± Vector
// Vector =
Scalar * Vector (scalar product)
// Segment with defining endpoints {Point P0, P1;}
//===================================================================
#define TRUE
1
#define FALSE 0
#define SMALL_NUM 0.00000001 // anything that avoids division overflow
#define dot(u,v) ((u).x * (v).x + (u).y * (v).y) // 2D
dot product
#define perp(u,v) ((u).x * (v).y - (u).y * (v).x) // 2D perp
product
// Note: see the April 2001
Algorithm for the "perp product"
//
intersect2D_SegPoly():
// Input: S = 2D segment to intersect with the
convex polygon
// n = number
of 2D points in the polygon
// V[] = array
of n+1 vertex points with V[n]=V[0]
// Note: The polygon MUST be convex and
//
have vertices oriented counterclockwise (ccw).
// This code
does not check for and verify these conditions.
// Output: *IS = the intersection segment (when it exists)
// Return: FALSE = no intersection
// TRUE
= a valid intersection segment exists
int
intersect2D_SegPoly( Segment S, Point* V, int n, Segment* IS)
{
if (S.P0 == S.P1) {
// the segment S is a single point
// test for inclusion of S.P0 in the
polygon
*IS = S;
// same point if inside polygon
return cn_PnPoly( S.P0, V, n );
// March 2001
Algorithm
}
float tE = 0;
// the maximum entering segment parameter
float tL = 1;
// the minimum leaving segment parameter
float t, N, D;
// intersect parameter t = N / D
Vector dS = S.P1 - S.P0; // the
segment direction vector
Vector e;
// edge vector
// Vector ne;
// edge outward normal (not explicit in code)
for (int i=0; i < n; i++) // process polygon edge
V[i]V[i+1]
{
e = V[i+1] - V[i];
N = perp(e, S.P0-V[i]);// = -dot(ne,
S.P0-V[i])
D = -perp(e, dS);
// = dot(ne, dS)
if (fabs(D) < SMALL_NUM) { // S is
nearly parallel to this edge
if (N < 0)
// P0 is outside this edge, so
return FALSE; // S is outside the polygon
else
// S cannot cross this edge, so
continue; // ignore this
edge
}
t = N / D;
if (D < 0) {
// segment S is entering across this edge
if (t > tE) {
// new max tE
tE = t;
if (tE > tL) // S enters after leaving polygon
return FALSE;
}
}
else {
// segment S is leaving across this edge
if (t < tL) {
// new min tL
tL = t;
if (tL < tE) // S leaves before entering polygon
return FALSE;
}
}
}
// tE <= tL implies that there is a valid intersection
subsegment
IS->P0 = S.P0 + tE * dS; // = P(tE) =
point where S enters polygon
IS->P1 = S.P0 + tL * dS; // = P(tL) =
point where S leaves polygon
return TRUE;
}
M. Cyrus & J. Beck, "Generalized Two- and Three-Dimensional Clipping", Computers and Graphics 3(1), 23-28 (1978)
James Foley, Andries van Dam, Steven Feiner & John Hughes, Computer Graphics (2nd Edition in C), Section 3.12.4 "A Parametric Line-Clipping Algorithm" (1996)
Eric Haines, "Fast Ray-Convex Polyhedron Intersection" in Graphics Gems II (1994)
Francis Hill, "The Pleasures of 'Perp Dot'
Products" in
Graphics Gems IV (1994)
[Note: the first critical definition has a typo, and should be: a^
= (-ay, ax).]
Y-D. Liang & B. Barsky, "A New Concept and Method for Line Clipping", ACM TOG 3(1), 1-22 (1984)
|
Copyright ©
2001-2006 softSurfer. All rights reserved. |