43

The program needs to read the values of three coordinates

  • P1(x1,y1)
  • P2(x2,y2)
  • P3(x3,y3)

as well as another coordinate P(x,y) and determine whether this point is inside a triangle formed from the 3 point above.

Seanny123
  • 8,776
  • 13
  • 68
  • 124
KevinKZ
  • 541
  • 1
  • 4
  • 6
  • 7
    This is simple mathematics, and probably belongs in programmers or Computer science. also duplicate of http://stackoverflow.com/questions/2049582/how-to-determine-a-point-in-a-triangle – Karthik T Nov 09 '12 at 01:40
  • 1
    You seem to have a reputation of just asking for solutions to homework problems. Read this whathaveyoutried.com and do a google search for 'tell if a point is inside a triangle' – Fantastic Mr Fox Nov 09 '12 at 01:43
  • I’m voting to close this question because it is better suited for math.stackexchange.com – Seanny123 Sep 08 '21 at 15:25
  • Does this answer your question? [How to determine if a point is in a 2D triangle?](https://stackoverflow.com/questions/2049582/how-to-determine-if-a-point-is-in-a-2d-triangle) – cigien Sep 08 '21 at 23:39

3 Answers3

65

The proper way to do this is by calculating the barycentric coordinates of the fourth point given the three points of your triangle. The formula to compute them is given at the end of the section "Converting to barycentric coordinates", but I hope to provide a less mathematics-intense explanation here.

Assume, for simplicity, that you have a struct, point, that has values x and y. You defined your points as:

point p1(x1, y1);
point p2(x2, y2);
point p3(x3, y3);

point p(x,y); // <-- You are checking if this point lies in the triangle.

Now, the barycentric coordinates, generally called alpha, beta, and gamma, are calculated as follows:

float alpha = ((p2.y - p3.y)*(p.x - p3.x) + (p3.x - p2.x)*(p.y - p3.y)) /
        ((p2.y - p3.y)*(p1.x - p3.x) + (p3.x - p2.x)*(p1.y - p3.y));
float beta = ((p3.y - p1.y)*(p.x - p3.x) + (p1.x - p3.x)*(p.y - p3.y)) /
       ((p2.y - p3.y)*(p1.x - p3.x) + (p3.x - p2.x)*(p1.y - p3.y));
float gamma = 1.0f - alpha - beta;

If all of alpha, beta, and gamma are greater than 0, then the point p lies within the triangle made of points p1, p2, and p3.

The explanation behind this is that a point inside a triangle can be described using the points of the triangle, and three coefficients (one for each point, in the range [0,1]):

p = (alpha)*p1 + (beta)*p2 + (gamma)*p3

Rearranging this function gives you the formula to compute barycentric coordinates, but I feel like the steps to do so might be beyond the scope of the question. They are provided on the Wikipedia page that I linked up top.

It follows that each coefficient must be greater than 0 in order for the point p to lie within the area described by the three points.

kevintodisco
  • 5,061
  • 1
  • 22
  • 28
  • keep in mind that I am still in high school and many of the things about barycentric coordinates are completely unknown to me. Any way, thanks :) – KevinKZ Nov 09 '12 at 01:59
  • 3
    That's why I hope to provide a clearer explanation in the answer :) – kevintodisco Nov 09 '12 at 02:01
  • your explanation was really helpful and I like this formula, i think it's much less complex, and I will try it out. Thanks for your help :) – KevinKZ Nov 09 '12 at 02:29
  • note that you have an error in the formula while calculating the alpha you'd be calculating the *det(**T**)* (see: [wikipedia](https://en.wikipedia.org/wiki/Barycentric_coordinate_system)). i.e., the sign is wrong in the denominator. – Avinash R Aug 08 '14 at 07:11
  • How do you deal with degenerate triangles? What if the denominator of alpha/beta is zero? – torr Sep 28 '14 at 05:43
  • 1
    If the denominator is zero then you have a collinear point, that is a point on the line between two of the points of the triangle. To cope with this you will want to calculate the denominator separately and check to see if it is zero and handle appropriately. – Dijkgraaf Nov 23 '14 at 00:04
  • thank you, the article is useful, easy-to-read and very interesting! shame on me and didn't know it before – Andrey Lyubimov Jul 31 '16 at 21:10
25

Instead of P1, P2 and P3, lets assume the points as A,B and C.

          A(10,30)
            / \
           /   \
          /     \
         /   P   \      P'
        /         \
B (0,0) ----------- C(20,0) 

Algorithm :

1) Calculate area of the given triangle, i.e., area of the triangle ABC in the above diagram. 

    Area A = [ x1(y2 - y3) + x2(y3 - y1) + x3(y1-y2)]/2

2) Calculate area of the triangle PAB. We can use the same formula for this. Let this area be A1.
3) Calculate area of the triangle PBC. Let this area be A2.
4) Calculate area of the triangle PAC. Let this area be A3.
5) If P lies inside the triangle, then A1 + A2 + A3 must be equal to A.

Given below is a program in C:

#include <stdio.h>
#include <stdlib.h>

/* A utility function to calculate area of triangle formed by (x1, y1), 
   (x2, y2) and (x3, y3) */
float area(int x1, int y1, int x2, int y2, int x3, int y3)
{
   return abs((x1*(y2-y3) + x2*(y3-y1)+ x3*(y1-y2))/2.0);
}

/* A function to check whether point P(x, y) lies inside the triangle formed 
   by A(x1, y1), B(x2, y2) and C(x3, y3) */
bool isInside(int x1, int y1, int x2, int y2, int x3, int y3, int x, int y)
{   
   /* Calculate area of triangle ABC */
   float A = area (x1, y1, x2, y2, x3, y3);

   /* Calculate area of triangle PBC */  
   float A1 = area (x, y, x2, y2, x3, y3);

   /* Calculate area of triangle PAC */  
   float A2 = area (x1, y1, x, y, x3, y3);

   /* Calculate area of triangle PAB */   
   float A3 = area (x1, y1, x2, y2, x, y);

   /* Check if sum of A1, A2 and A3 is same as A */
   return (A == A1 + A2 + A3);
}

/* Driver program to test above function */
int main()
{
   /* Let us check whether the point P(10, 15) lies inside the triangle 
      formed by A(0, 0), B(20, 0) and C(10, 30) */
   if (isInside(0, 0, 20, 0, 10, 30, 10, 15))
     printf ("Inside");
   else
     printf ("Not Inside");

   return 0;
}

Time : O(1)

Space: O(1)

Ayush
  • 2,608
  • 2
  • 22
  • 31
  • 9
    Beware when comparing floating point types with `==`. Most of the time it won't work as expected http://stackoverflow.com/questions/10334688/how-dangerous-is-it-to-compare-floating-point-values?rq=1 – phuclv Dec 02 '14 at 18:23
  • 1
    @Lưu Vĩnh Phúc If we know in advance that all input points are integers, we can skip dividing by two while calculating the area which will rid us of the float accuracy issue. But if points are not integers, then we could define a small value epsilon above and below the area under which the error will be tolerated. – jahackbeth Oct 12 '15 at 06:18
  • 2
    I like this approach very much. – Andrey Lyubimov Jul 31 '16 at 13:04
  • Is it not possible that there might be a point P' with the same area as that of the point inside the triangle? – thebenman Aug 17 '16 at 03:41
5

Take the average of the three given points. This new point P4 will always lie inside the triangle.

Now check if P and P4 lie on the same side of each of the three lines P1P2 P2P3 and P3P1. You can do this by checking the signs of the cross products (P -> P1) x (P -> P2) and (P4 -> P1) x (P4 -> P2) (where P->P1 is the vector from P to P1), and then the other two pairs.

irrelephant
  • 4,091
  • 2
  • 25
  • 41
  • and how doe you take the average of the three points? We have x and y of a point in this case – KevinKZ Nov 09 '12 at 01:42
  • @KevinKZ `( (P1_x + P2_x + P3_x) / 3, (P1_y + P2_y + P3_y) / 3)` – irrelephant Nov 09 '12 at 01:44
  • I came up with another idea: If the area of the big triangle is equal to the sum of the areas formed by the smaller triangles(in this case, a smaller triangle is a triangle formed from two of the points such as P1, P2 or P3 and the point P) then this means that the point lies inside a triangle. Am I right? Will this work? – KevinKZ Nov 09 '12 at 01:55
  • 1
    @KevinKZ Yes, I think so. It'll say that a point on the perimeter is inside the triangle, though. http://en.wikipedia.org/wiki/Shoelace_formula to find the areas. – irrelephant Nov 09 '12 at 02:09
  • i found this other one, which I think it's simpler, using the hero's formula and the distance formula. What do you think? – KevinKZ Nov 09 '12 at 02:19
  • @KevinKZ Well, it basically doesn't matter. :-) – irrelephant Nov 09 '12 at 02:21
  • why take average of 3 points of triangle. Instead check for P and P1 lie on same side of P2P3 and all other respective lines. – nbsrujan Aug 30 '16 at 11:40