Is there an easy way to determine if a point is inside a triangle? It's 2D, not 3D.
相关问题
- Finding k smallest elements in a min heap - worst-
- binary search tree path list
- High cost encryption but less cost decryption
- d3.js moving average with previous and next data v
- How to get a fixed number of evenly spaced points
相关文章
- What are the problems associated to Best First Sea
- ceil conterpart for Math.floorDiv in Java?
- Coin change DP solution to keep track of coins
- why 48 bit seed in util Random class?
- Algorithm for partially filling a polygonal mesh
- Robust polygon normal calculation
- Algorithm for maximizing coverage of rectangular a
- Need help generating discrete random numbers from
I just want to use some simple vector math to explain the barycentric coordinates solution which Andreas had given, it will be way easier to understand.
(1-s)|v0v2| / |v0v2| = tp|v0v1| / |v0v1|
we get 1 - s = tp, then 1 = s + tp. If any t > tp, which 1 < s + t where is on the double dash line, the vector is outside the triangle, any t <= tp, which 1 >= s + t where is on single dash line, the vector is inside the triangle.
Then if we given any s in [0, 1], the corresponding t must meet 1 >= s + t, for the vector inside triangle.
So finally we get v = s * v02 + t * v01, v is inside triangle with condition s, t, s+t belongs to [0, 1]. Then translate to point, we have
p - p0 = s * (p1 - p0) + t * (p2 - p0), with s, t, s + t in [0, 1]
which is the same as Andreas' solution to solve equation system p = p0 + s * (p1 - p0) + t * (p2 - p0), with s, t, s + t belong to [0, 1].
In general, the simplest (and quite optimal) algorithm is checking on which side of the half-plane created by the edges the point is.
Here's some high quality info in this topic on GameDev, including performance issues.
And here's some code to get you started:
By using the analytic solution to the barycentric coordinates (pointed out by Andreas Brinck) and:
one can minimize the number of "costy" operations:
(code can be pasted in Perro Azul jsfiddle)
Leading to:
This compares quite well with Kornel Kisielewicz solution (25 recalls, 1 storage, 15 substractions, 6 multiplications, 5 comparisons), and might be even better if clockwise/counter-clockwise detection is needed (which takes 6 recalls, 1 addition, 2 substractions, 2 multiplications and 1 comparison in itself, using the analytic solution determinant, as pointed out by rhgb).
Supposedly high-performance code which I adapted in JavaScript(article below):
pointInTriangle (p, p0, p1, p2) - for counter-clockwise triangles
pointInTriangle (p, p0, p1, p2) - for clockwise triangles
Look in jsFiddle (performance test included), there's also winding checking in a separate function http://jsfiddle.net/z7x0udf7/3/
Inspired by this: http://www.phatcode.net/articles.php?id=459
I agree with Andreas Brinck, barycentric coordinates are very convenient for this task. Note that there is no need to solve an equation system every time: just evaluate the analytical solution. Using Andreas' notation, the solution is:
where
Area
is the (signed) area of the triangle:Just evaluate
s
,t
and1-s-t
. The pointp
is inside the triangle if and only if they are all positive.EDIT: Note that the above expression for the area assumes that the triangle node numbering is counter-clockwise. If the numbering is clockwise, this expression will return a negative area (but with correct magnitude). The test itself (
s>0 && t>0 && 1-s-t>0
) doesn't depend on the direction of the numbering, however, since the expressions above that are multiplied by1/(2*Area)
also change sign if the triangle node orientation changes.EDIT 2: For an even better computational efficiency, see coproc's comment below (which makes the point that if the orientation of the triangle nodes (clockwise or counter-clockwise) is known beforehand, the division by
2*Area
in the expressions fors
andt
can be avoided). See also Perro Azul's jsfiddle-code in the comments under Andreas Brinck's answer.Other function in python, faster than Developer's method (for me at least) and inspired by Cédric Dufour solution:
You can test it with:
It takes a lot to plot, but that grid is tested in 0.0195319652557 seconds against 0.0844349861145 seconds of Developer's code.
Finally the code comment: