测试3D点是否在3D多面体内

时间:2017-06-13 06:09:07

标签: triangulation point-in-polygon

给定由三角网格表示的边界定义的三维多面体,如何实现一个算法来确定给定的3D点是否属于多面体的内部?

1 个答案:

答案 0 :(得分:1)

有几种方法可以实现此功能。

最简单的方法是从点开始创建无限光线(或非常长的线段)并指向任意方向,然后计算光线和三角形之间的交叉点数。如果交点的数量是奇数,则该点在多面体内。

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

现在计算一个段和一个三角形之间是否存在交叉的函数:

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

最后,orient3d函数:

   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

现在有两个大问题:

  1. 如果浮点精度不够,会发生什么 计算Orient3d?

  2. 当所选片段完全通过a时会发生什么 顶点或三角形的边缘?

  3. 对于1.,必须使用任意精确的算术[1]。在[2]中,参考文献[1](Jonathan Shewchuk)的作者公开了orient3d()的实现。 Geogram中还有一个实现,我自己的编程库[3]。

    现在为2.,它更棘手,最好的方法是实现符号扰动[4]。简而言之,我们的想法是“消除歧义”配置,其中orient3d()通过考虑点沿着时间参数化的轨迹移动而返回零,并且当时间趋于零时采用位置的限制(另一种说法:如果位置没有给出答案,请在时间t = 0时查看“速度矢量”。原始参考文献[4]给出了“多边形点”测试(问题的2D版本)的orient2d()的符号扰动。

    注意:如果你很懒并且你不想实现符号扰动,你可以在每次orient3d()测试返回零时选择一个随机方向(那么你不能保证它不会永远搜索,但是练习它不太可能发生)。无论如何,我建议仅将其用于原型设计,并最终实现符号扰动。

    [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