Testing whether a 3D point is inside a 3D polyhedron

爱⌒轻易说出口 提交于 2020-12-13 05:58:10

问题


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:

  1. what happens if floating point precision is not sufficient when computing Orient3d ?

  2. 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!