Find if a point is within a triangle: Difference between revisions

→‎{{header|Evaldraw}}: add image, fixed tri area which is just halved not sq
(→‎{{header|Evaldraw}}: add solution for point in tri)
(→‎{{header|Evaldraw}}: add image, fixed tri area which is just halved not sq)
Line 1,166:
 
This solution makes use of the x,y plotting function. It allows us to plot an arbitrary function of x,y and set r,g,b colors before we return. This allows us to test all points in the cartesian space and we can pan and zoom the viewport, or mouse over an x,y position we want to see the computed RGB value for. The isPointInside function here works in similar way to many other solutions here, for the 3 points of a triangle we compute 3 line equations. The line equations when evaluated for a x,y point give the distance from the point to the line. The distance is signed. We can use this to return early from isPointInside. Only if all three lines give a result with the same sign can the point be classified as inside the triangle. We can use this property of sidedness and sign to make the method work for both clockwise and anti-clockwise specification of the triangle vertices. If the triangle is clockwise, then the area function returns a positive value. If the triangle is anti clockwise, then the area function returns a negative value, and we can multiply the sgn checks by -1 so a point can still be considered inside.
 
[[File:Evaldraw points in triangle.png|thumb|alt=A triangle with vertices set to red, green and blue with interpolation over surface.|plot mode (x,y,&r,&g,&b) allows for plotting of arbitrary functions of (x,y) and return rgb]]
 
<syntaxhighlight lang="c">struct vec2{x,y;};
Line 1,171 ⟶ 1,173:
 
// Our triangle defined by 3 points in the cartesian 2D plane.
static vec2 vertices[3] = {0,-2, -2,2, 4,0};
//static vec2 vertices[3] = {0,-2, 4,0, -2,2};
enum{WIND_ANTI_CLOCKWISE=-1, WIND_CLOCKWISE=1}
static winding_dir = -1; // +1 if clockwise (positive angle) -1 if negative.
static line_t line0, line1, line2;
static areaSqarea2; // 2x tri area
(x,y,t,&r,&g,&b)
{
Line 1,184 ⟶ 1,185:
// we may want to test for a given triangle.
// In a real program, you may want to store this with the triangle.
//static vec2 verticesdat[3] = {0,-2, 4,0, -2,2, 4,0};
for(i=0; i<3; i++) {
vertices[i].x = dat[i].x + 2;
vertices[i].y = dat[i].y + 2;
}
makeLine(line0, vertices[0], vertices[1]);
makeLine(line1, vertices[1], vertices[2]);
makeLine(line2, vertices[2], vertices[0]);
areaSqarea2 = areaTriangleSquareareaTriangleX2(vertices[0], vertices[1], vertices[2]);
winding_dir = sgn(areaSqarea2);
}
Line 1,195 ⟶ 1,201:
if ( isPointInside( screenPoint, line0, line1, line2, d0, d1, d2) ) {
if (winding_dir == -1) {
swap(d0,d2d1);
}
r = 255*( d1 / areaSqarea2);
g = 255*( d2 / areaSqarea2);
b = 255*( d0 / areaSqarea2);
if (d0==0) {r=255; g=0; }
if (d1==0) {r=255; g=0; }
Line 1,231 ⟶ 1,237:
x*line.a + y*line.b + line.c;
}
areaTriangleSquareareaTriangleX2(vec2 a, vec2 b, vec2 c) { // Same as the determinant, but dont div by 2
( a.x*(b.y - c.y) + b.x*(c.y - b.y) + c.x*(a.y - b.y) );
}
swap(&a,&b) {tmp = a; a=b; b=tmp; }</syntaxhighlight>
63

edits