问题
Given a 3D polyhedron defined by its boundary represented by a triangulated mesh, how can I implement an algorithm that determines whether a given 3D point belongs to the interior of the polyhedron ?
回答1:
There are several ways of implementing this function.
The simplest one is to create an infinite ray (or a very long segment) starting from the point and pointing towards an arbitrary direction, then counting the number of intersections between the ray and the triangles. If the number of intersections is odd, then the point is inside the polyhedron.
Inside(Polyhedron P, point q)
Segment S = [q, q+(0,0,1e30)]
count = 0
For each triangle T of P
If Intersect(S,T)
count = count + 1
End if
End for
return odd(count)
End
Now the function that computes whether there is an intersection between a segment and a triangle:
Intersect([q1,q2],(t1,t2,t3))
s1 = orient3d(q1,t1,t2,t3)
s2 = orient3d(q2,t1,t2,t3)
// Test whether the two extermities of the segment
// are on the same side of the supporting plane of
// the triangle
If(s1 == s2)
return false
End if
// Now we know that the segment 'straddles' the supporing
// plane. We need to test whether the three tetrahedra formed
// by the segment and the three edges of the triangle have
// the same orientation
s3 = orient3d(q1,q2,t1,t2)
s4 = orient3d(q1,q2,t2,t3)
s5 = orient3d(q1,q2,t3,t1)
return (s3 == s4 AND s4 == s5)
End
Finally, the orient3d function:
Orient3d(a,b,c,d)
// Computes the sign of the signed volume
// of the tetrahedron (a,b,c,d)
return Sign( dot(cross(b-a,c-a),d-a) )
End
Now there are two big gotchas:
what happens if floating point precision is not sufficient when computing Orient3d ?
what happens when the chosen segment passes exactly through a vertex or an edge of a triangle ?
For 1., one has to use arbitrary precision arithmetics [1]. There is a publicly available implementation of orient3d() by the author of reference [1] (Jonathan Shewchuk) in [2]. There is also an implementation in Geogram, my own programming library [3].
Now for 2., it is more tricky, the best way is to implement symbolic perturbations [4]. In a nutshell, the idea is to 'disambiguate' configurations where orient3d() returns zero by considering that the points are moving along trajectories parameterized by time, and taking the limit of the position when time tends to zero (another way of saying that: if position does not give the answer, take a look at the 'speed vector' at time t=0). The original reference [4] gives the symbolic perturbation for orient2d() for the "point in polygon" test (the 2D version of your problem).
Note: if you are lazy and you do not want to implement symbolic perturbation, you can pick a random direction everytime one of the orient3d() tests returns zero (then you have no guarantee that it will not search forever, but in practice it is very unlikely to occur). Anyway I'd recommend to use that only for prototyping, and implement symbolic perturbation in the end.
[1] https://people.eecs.berkeley.edu/~jrs/papers/robustr.pdf
[2] https://www.cs.cmu.edu/~quake/robust.html
[3] http://alice.loria.fr/software/geogram/doc/html/index.html
[4] http://dl.acm.org/citation.cfm?id=77639
来源:https://stackoverflow.com/questions/44513525/testing-whether-a-3d-point-is-inside-a-3d-polyhedron