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
If you are looking for speed, here is a procedure that might help you.
Sort the triangle vertices on their ordinates. This takes at worst three comparisons. Let Y0, Y1, Y2 be the three sorted values. By drawing three horizontals through them you partition the plane into two half planes and two slabs. Let Y be the ordinate of the query point.
Costs two more comparisons. As you see, quick rejection is achieved for points outside of the "bounding slab".
Optionally, you can supply a test on the abscissas for quick rejection on the left and on the right (
X <= X0' or X >= X2'
). This will implement a quick bounding box test at the same time, but you'll need to sort on the abscissas too.Eventually you will need to compute the sign of the given point with respect to the two sides of the triangle that delimit the relevant slab (upper or lower). The test has the form:
The complete discussion of
i, j, k
combinations (there are six of them, based on the outcome of the sort) is out of the scope of this answer and "left as an exercise to the reader"; for efficiency, they should be hard-coded.If you think that this solution is complex, observe that it mainly involves simple comparisons (some of which can be precomputed), plus 6 subtractions and 4 multiplies in case the bounding box test fails. The latter cost is hard to beat as in the worst case you cannot avoid comparing the test point against two sides (no method in other answers has a lower cost, some make it worse, like 15 subtractions and 6 multiplies, sometimes divisions).
UPDATE: Faster with a shear transform
As explained just above, you can quickly locate the point inside one of the four horizontal bands delimited by the three vertex ordinates, using two comparisons.
You can optionally perform one or two extra X tests to check insideness to the bounding box (dotted lines).
Then consider the "shear" transform given by
X'= X - m Y, Y' = Y
, wherem
is the slopeDX/DY
for the highest edge. This transform will make this side of the triangle vertical. And since you know on what side of the middle horizontal you are, it suffices to test the sign with respect to a single side of the triangle.Assuming you precomputed the slope
m
, as well as theX'
for the sheared triangle vertices and the coefficients of the equations of the sides asX = m Y + p
, you will need in the worst caseX' = X - m Y
;X >< m' Y + p'
against the relevant side of the sheared triangle.If you know the co-ordinates of the three vertices and the co-ordinates of the specific point, then you can get the area of the complete triangle. Afterwards, calculate the area of the three triangle segments (one point being the point given and the other two being any two vertices of the triangle). Thus, you will get the area of the three triangle segments. If the sum of these areas are equal to the total area (that you got previously), then, the point should be inside the triangle. Otherwise, the point is not inside the triangle. This should work. If there are any issues, let me know. Thank you.
Here is an efficient Python implementation:
and an example output:
I wrote this code before a final attempt with Google and finding this page, so I thought I'd share it. It is basically an optimized version of Kisielewicz answer. I looked into the Barycentric method also but judging from the Wikipedia article I have a hard time seeing how it is more efficient (I'm guessing there is some deeper equivalence). Anyway, this algorithm has the advantage of not using division; a potential problem is the behavior of the edge detection depending on orientation.
In words, the idea is this: Is the point s to the left of or to the right of both the lines AB and AC? If true, it can't be inside. If false, it is at least inside the "cones" that satisfy the condition. Now since we know that a point inside a trigon (triangle) must be to the same side of AB as BC (and also CA), we check if they differ. If they do, s can't possibly be inside, otherwise s must be inside.
Some keywords in the calculations are line half-planes and the determinant (2x2 cross product). Perhaps a more pedagogical way is probably to think of it as a point being inside iff it's to the same side (left or right) to each of the lines AB, BC and CA. The above way seemed a better fit for some optimization however.
A simple way is to:
Two good sites that explain alternatives are:
blackpawn and wolfram
I needed point in triangle check in "controlable environment" when you're absolutely sure that triangles will be clockwise. So, I took Perro Azul's jsfiddle and modified it as suggested by coproc for such cases; also removed redundant 0.5 and 2 multiplications because they're just cancel each other.
http://jsfiddle.net/dog_funtom/H7D7g/
Here is equivalent C# code for Unity: