confusing.c - OpenLearning
/*
 * 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)

Comments

Chat