Numerical stability of the point-triangle test with barycentric coordinates

Looking at the various point-triangle testing methods (2D case), I found that a method that uses barycentric coordinates is the most used. Here is StackOverflow's answer that explains this.

Why is this method the most preferred? This is probably due to smaller calculations, but what about numerical stability? Is this algorithm more suitable than, say, the “same side” method for cases where the point is especially close to the boundary?

+4
source share
1 answer

If you decide it:

p = p0 + (p1 - p0) * s + (p2 - p0) * t
s = <0.0,1.0>
t = <0.0,1.0>
s+t<=1.0

Competing with this system:

p.a = p0.a + (p1.a - p0.a) * s + (p2.a - p0.a) * t
p.b = p0.b + (p1.b - p0.b) * s + (p2.b - p0.b) * t
----------------------------------------------------

You have two algebraic options:

I.  t = (p.a - p0.a - (p1.a - p0.a) * s) / (p2.a - p0.a)
II. p.b = p0.b + (p1.b - p0.b) * s + (p2.b - p0.b) * t
----------------------------------------------------
II. p.b = p0.b + (p1.b - p0.b) * s + (p2.b - p0.b) * (p.a - p0.a - (p1.a - p0.a) * s) / (p2.a - p0.a)
II. s = (p.b-p0.b) / ( (p1.b-p0.b) + ( (p2.b-p0.b)*(p.a-p0.a-(p1.a-p0.a)/(p2.a-p0.a) ) )
...

and

I.  s = (p.a - p0.a - (p2.a - p0.a) * t) / (p1.a - p0.a)
II. p.b = p0.b + (p1.b - p0.b) * s + (p2.b - p0.b) * t
----------------------------------------------------
...

Which gives you 2 options for an algebraic solution. To ensure stability, you must share with large enough values. Therefore, you must select the axes ( a,bx,y) and the order of the points so that you are not divided by zero or small values.

To avoid this, you can use a matrix approach

p.a = p0.a + (p1.a - p0.a) * s + (p2.a - p0.a) * t
p.b = p0.b + (p1.b - p0.b) * s + (p2.b - p0.b) * t
--------------------------------------------------
|p.a|   | (p1.a - p0.a) , (p2.a - p0.a) , p0.a |   | s |
|p.b| = | (p1.b - p0.b) , (p2.b - p0.b) , p0.b | * | t |
| 1 |   |       0       ,       0     ,     1  |   | 1 |
--------------------------------------------------------
| s |           | (p1.a - p0.a) , (p2.a - p0.a) , p0.a |   | p.a |
| t | = inverse | (p1.b - p0.b) , (p2.b - p0.b) , p0.b | * | p.b |
| 1 |           |       0       ,       0       ,   1  |   |  1  |
------------------------------------------------------------------

Also here you got more options for axis order, point order, so that the inverse matrix is ​​computable. If you use the sublimit approach for the inverse matrix solution, then the only thing that matters is the final division step. Thus, you can select orders until you get a nonzero determinant.

+2

All Articles