假定四面体的四个顶点为:
V1 = (x1, y1, z1) V2 = (x2, y2, z2) V3 = (x3, y3, z3) V4 = (x4, y4, z4) 你测试的空间点为: P = (x, y, z)
如果下面的 5 个行列式有相同的符号,则点 P在四面体内:
|x1 y1 z1 1| D0 = |x2 y2 z2 1| |x3 y3 z3 1| |x4 y4 z4 1| |x y z 1| D1 = |x2 y2 z2 1| |x3 y3 z3 1| |x4 y4 z4 1| |x1 y1 z1 1| D2 = |x y z 1| |x3 y3 z3 1| |x4 y4 z4 1| |x1 y1 z1 1| D3 = |x2 y2 z2 1| |x y z 1| |x4 y4 z4 1| |x1 y1 z1 1| D4 = |x2 y2 z2 1| |x3 y3 z3 1| |x y z 1|
需要注意的一些情况 :
如果正好 D0=0, 则该四面体是退化的四面体 ( 比如退化成三角形, 此时四 点共面) 。
如果 Di=0(i 不等于 0) ,则 P位于四面体的边界面 i 上 ( 边界面 i 是指 和 Vi 相对应的其它三个顶点形成的面 ) 。
如果 Di 的符号和 D0不同,则 Di 位于边界面 i 的外边。
如果所有 Di 的符号都和 D0相同,则 P 位于边界面 i 之内( 在四个边界面 内,就是在四面体之内 ) 。
等式 D0 = D1+D2+D3+D4成立。
这个公式能够扩展到任何维的单纯形 ( 在2D情况下是三角形, 在3D情况 下是四面体 ) 。 注意 :bi = Di/D0 就是通常的重心坐标。 注意 :比较 Di 和 D0的符号仅是判定 P和 Vi 是否在边界面 i 的同一边。
// 由给定的三个顶点的坐标,计算三角形面积。 // Point(java.awt.Point) private
代表点的坐标。
static double triangleArea(Point pos1, Point pos2, Point pos3) {
double result = Math.abs((pos1.x * pos2.y + pos2.x * pos3.y + pos3.x * pos1. y
- pos2.x * pos1.y - pos3.x * pos2.y - pos1.x * pos3.y) / 2.0D); return result; }
// 判断点 pos 是否在指定的三角形内。 private
static boolean inTriangle(Point pos, Point posA, Point posB, Point posC) {
double triangleArea = triangleArea(posA, posB, posC); double area = triangleArea(pos, posA, posB); area += triangleArea(pos, posA, posC); area += triangleArea(pos, posB, posC); double epsilon = 0.0001;
// 由于浮点数的计算存在着误差,故指定一个足够小的数,
用于判定两个面积是否 ( 近似) 相等。
if (Math.abs(triangleArea - area) < epsilon) {
return } return }
false ;
true ;
相关推荐: