/*
* Test if a point is inside a triangle.
* Julian Saknussemm
*
* Given Three points of a triangle, and another arbitrary point this program determines if
* that point lies inside the triangle.
*
* This is determined by satisfying the following rule:
* A point P(x,y) is inside triangle A(x0,y0), B(x1,y1), C(x2,y2)
* iff
* P is on the same side of the line AB as C
* P is on the same side of the line BC as A
* and
* P is on the same side of the line AC as B
*
* A special case exits for a vertical line (inf gradient) when testing the side of the line
*/
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#define ON 0
#define UNDER -1
#define OVER 1
// function prototypes
void testRight (void);
int testLine (double px, double py, double m, double b);
int testTwoPoints (double px, double py, double m, double b, double lx, double ly);
int verticalTest (double x0, double y0, double x1, double y1,
double x2, double y2, double px, double py);
int main(int argc, char* argv[]) {
void testRight (void);
double x0;
double y0;
double x1;
double y1;
double x2;
double y2;
double px;
double py;
// All scanf values summed together into one
int numOfInputs = 0;
// get input and
printf("Triangle Vertex A (x,y): \n");
numOfInputs += scanf("%lf,%lf", &x0, &y0);
printf("Triangle Vertex B (x,y): \n");
numOfInputs += scanf("%lf,%lf", &x1, &y1);
printf("Triangle Vertex C (x,y): \n");
numOfInputs += scanf("%lf,%lf", &x2, &y2);
printf("Test Point (x,y): \n");
numOfInputs += scanf("%lf,%lf", &px, &py);
// print error and abort if the required number of inputs is not given
if (numOfInputs != 8) {
printf("You're stupid and didn't put in the right inputs!\n");
printf("Please place a comma between arguments.\n");
}
assert (numOfInputs == 8);
// print answer
printf("Point (%.2lf,%.2lf) is ", px,py);
if (verticalTest(x0, y0, x1, y1, x2, y2, px, py)) {
printf("inside the triangle\n");
} else {
printf("outside the triangle\n");
}
return EXIT_SUCCESS;
}
void testRight (void) {
assert (verticalTest(0, 0, 10, 0, 0, 10, 20, 20) == 0);
assert (verticalTest(0, 0, 10, 0, 0, 10, 0, 0) == 1);
assert (verticalTest(0, 0, 10, 0, 0, 10, 1, 1) == 1);
assert (verticalTest(0, 0, 10, 0, 0, 10, -2, -42) == 0);
assert (verticalTest(0, 0, 10, 0, 0, 10, 0, 5) == 1);
}
// Tests if point is under on or over a line
int testLine (double px, double py, double m, double b) {
int position;
if( py < m * px + b ) {
position = UNDER;
} else if ( py == m * px + b ) {
position = ON;
} else {
position = OVER;
}
return position;
}
// Test if two points lie on the same side of a line
int testTwoPoints (double px, double py, double m, double b, double lx, double ly) {
return (testLine(px, py, m, b) == testLine(lx, ly, m, b));
}
int verticalTest (double x0, double y0, double x1, double y1,
double x2, double y2, double px, double py) {
int line1;
int line2;
int line3;
// line eqns
double m01 = (y1-y0)/(x1-x0);
double b01 = m01 * - x1 + y1;
double m02 = (y2-y0)/(x2-x0);
double b02 = m02 * -x2 + y2;
double m12 = (y2-y1)/(x2-x1);
double b12 = m12 * -x2 + y2;
// vertical line checks
if (x1 == x0) {
line1 = ((px <= x0) == (x2 <= x0));
} else {
line1 = testTwoPoints (px, py, m01, b01, x2, y2);
}
if (x1 == x2) {
line2 = ((px <= x2) == (x0 <= x2));
} else {
line2 = testTwoPoints (px, py, m12, b12, x0, y0);
}
if (x2 == x0) {
line3 = ((px <= x0 ) == (x1 <= x0));
} else {
line3 = testTwoPoints(px, py, m02, b02, x1, y1);
}
return (line1 && line2 && line3);
}
Download file:
confusing.c
(3.9 KB)