In 3D coordinates, point judgment is much more complicated. If google "Point in triangle" is the first search result on this webpage, it is a pity that the author did not discuss the result further and did not provide a good implementation, in addition, all the conclusions are valid only when the four-point common area is known.
We have already proved that the area method and the vector same direction method are equivalent.
AB × ac = AB × ap + ap × ac + pb × pc
| AB × ac | = | AB × ap | + | ap × ac | + | pb × pc |
Because the four vectors AB × ac, AB × ap, ap × ac, and pb × pc are in the same direction in parallel, therefore, we can first determine whether the four points a, B, c, and p are in common (by calculating the hybrid product). If they are in common, the four vectors must be in the same line, then, you only need to determine whether the last three vectors are in the same direction as the first vector (AB × ac) (you can determine the positive and negative values of the dot product between the last three vectors and the first vector ).
Code:
# Include <cfloat>
Template <typename T> class Vec3 {
T x, y, z;
Public:
Vec3 (T xx, T yy, T zz): x (xx), y (yy), z (zz ){}
Vec3 operator-(const Vec3 & v) const {return Vec3 (x-v. x, y-v. y, z-v. z );}
T dot (const Vec3 & v) const {return x * v. x + y * v. y + z * v. z ;}
Vec3 cross (const Vec3 & v) const {
Return Vec3 (y * v. z-z * v. y, z * v. x-x * v. z, x * v. y-y * v. x );
}
};
Typedef Vec3 <double> V3d;
// Method 1
Bool is_in_triangle3a (const V3d & a, const V3d & B, const V3d & c, const V3d & p)
{
V3d AB (B-a), ac (c-a), ap (p-);
If (fabs (AB. cross (ac). dot (ap)> = DBL_EPSILON) return false; // four-point non-co-occurrence
V3d abc = AB. cross (ac), abp = AB. cross (ap), apc = ap. cross (ac );
Double t0 = abc. dot (abc), t1 = abp. dot (abc), t2 = apc. dot (abc );
// T1> = 0 t2> = 0 t1 + t2 <= t0 t0 must be greater than 0
// Return (t1> =-DBL_EPSILON) & (t2> =-DBL_EPSILON) & (t0-t1-t2> =-DBL_EPSILON );
Double delta = fabs (t1) + fabs (t2) + fabs (t0-t1-t2)-t0;
Return fabs (delta) <DBL_EPSILON;
Method 1 requires 30 times of multiplication. Even if it is known that there are four common points, it still requires 27 times of multiplication calculation, saving only three times of multiplication calculation. Considering that each calculation of the vector product requires 6 multiplication calculations, and the calculation of the Point product requires only three multiplication calculations, you can consider eliminating the vector product calculation:
Formula:
(A × B) · c = (c × a) · B (hybrid product)
A × (B × c) = B (a · c) −c (a · B) (Laplace formula)
Available:
(A × B) · (a × c) = (a × c) × a) · B = (a · a) c-(a · c)) · B
= (A · a) * (B · c)-(a · c) * (a · B)
You can use this expansion:
// Method 2
Bool is_in_triangle3b (const V3d & a, const V3d & B, const V3d & c, const V3d & p)
V3d AB (B-a), ac (c-a), ap (p-);
If (fabs (AB. cross (ac). dot (ap)> = DBL_EPSILON) return false; // four-point non-co-occurrence
V3d abc = AB. cross (ac), abp = AB. cross (ap), apc = ap. cross (ac );
// Double t0 = abc. dot (abc), t1 = abp. dot (abc), t2 = apc. dot (abc); // expand the three calculation formulas.
Double v11 = AB. dot (AB), v22 = ac. dot (ac), v12 = AB. dot (ac );
Double v13 = AB. dot (ap), v23 = ac. dot (ap );
Double t0 = v11 * v22-v12 * v12;
Double t1 = v11 * v23-v12 * v13;
Double t2 = v22 * v13-v12 * v23;
Double delta = fabs (t1) + fabs (t2) + fabs (t0-t1-t2)-t0;
Return fabs (delta) <DBL_EPSILON;
Method 2: it requires 30 times of multiplication calculation, but only 21 times of multiplication calculation is required when four-point common surfaces are known.
The above two methods are easy to implement: method 1, easy to remember, and the efficiency is similar to method 2 (or even slightly higher) when the four-point common area cannot be determined ); the biggest advantage of method 2 is that when we know the four-point common surface, we use 6 times less multiplication than method 1, but it is really troublesome to implement it. Is there a better way? The answer is yes. This is the method to be mentioned later (only 13 times for conditional judgment (8 times for four-point total surfaces )).