0

I've done some research and there are many methods to doing this if the vertices and points are predetermined as seen here. However in my case, everything is specified by the user. The code I have put together (with the help of others), allows the user to create the polygon, and place points. I wrote functions to try and create vectors from the point to the vertices and then compute the angle. If it comes to 360 it should be inside and it should be colored green. Else it should be outside and red.

This is what I've been working on, but I cant seem to figure it out: (Edit: Included my entire code)

GLint vert[100][2];
int width = 400, height = 600, n = 0, m = 0, type = GL_LINE_STRIP, v;
bool rubberbanding = false;
bool closed = false;

double testx, testy;
bool isitin;

double dotp(double x1, double y1, double x2, double y2) {
    double a;
    a = (x1 * x2) + (y1 * y2);
    return a;
}

double mag(double x1, double y1, double x2, double y2) {
    double a;
    double x = (x2 - x1);
    double y = (y2 - y1);
    a = sqrt((x*x) + (y*y));
    return a;
}


bool inpoly(int numv, GLint vx[][2], GLint vy[][2], double tx, double ty) {
    double angle = 0.0;
    int n = 0;
    while (n != numv) {
        //vector from point to vertex
        double newv1x = vx[n][0] - tx;
        double newv1y = vy[n][1] - ty;
        double magv1 = mag(tx, ty, vx[n][0], vy[n][1]); //magnitude of vector

        //vector from point to next vertex
        double newv2x = vx[n + 1][0] - tx;
        double newv2y = vy[n + 1][1] - ty;
        double magv2 = mag(tx, ty, vx[n+1][0], vy[n+1][1]);//magnitude of vector

        //dot product between the two vectors
        double dp = dotp(newv1x, newv1y, newv2x, newv2y);

        //angle between two vectors
        double vang = acos(dp / (magv1*magv2));

        angle += vang;

        n++;
    }

    //vector from point to last vertex
    double newv1x = vx[numv][0] - tx;
    double newv1y = vy[numv][1] - ty;
    double magv1 = mag(tx, ty, vx[numv][0], vy[numv][1]); //magnitude of vector

    //vector from point to first vertex
    double newv2x = vx[0][0] - tx;
    double newv2y = vy[0][1] - ty;
    double magv2 = mag(tx, ty, vx[0][0], vy[0][1]);//magnitude of vector

    //dot product between the two vectors
    double dp = dotp(newv1x, newv1y, newv2x, newv2y);

    //angle between two vectors
    double vang = acos(dp / (magv1*magv2));

    angle += vang;

    if (angle == 360.0) return true;

    return false;

}




void display(){
     glClear(GL_COLOR_BUFFER_BIT);
     glColor3f(1, 1, 0);
     glBegin(closed ? GL_LINE_LOOP : GL_LINE_STRIP);
     for(int i = 0; i < m; i++){
             glVertex2iv(vert[i]);
     }
     glEnd();
     /*
     glColor3f(0, 0, 1);
     glBegin(GL_POINTS);
     for (int i = m; i < n; i++) {
         glVertex2iv(vert[i]);
     }
     */

     isitin = inpoly(m, vert, vert, testx, testy);

     if (isitin == true) {
         glColor3f(0, 1, 0);
         glBegin(GL_POINTS);
         for (int i = m; i < n; i++) {
             glVertex2iv(vert[i]);
         }
     }
     else {
         glColor3f(1, 0, 0);
         glBegin(GL_POINTS);
         for (int i = m; i < n; i++) {
             glVertex2iv(vert[i]);
         }
     }

     glEnd();
     glutSwapBuffers();
     glutPostRedisplay();
}

void keyboard(unsigned char key, int x, int y){
     switch(key){
                 case 'r': n = 0; m = 0; closed = false; break;

                 case 'c': closed = true; break;
     }
     glutPostRedisplay();
}

int findVertex(int x, int y){
    int dx, dy;
    for(int i = 0; i < n; i++){
            dx = vert[i][0] - x;
            dy = vert[i][1] - y;
            if(dx*dx + dy*dy < 16) return i;
    }
    return - 1;
}

void mousemove(int x, int y)
{
    testx = x;
    testy = height - 1 - y;
}

void mouse(int button, int state, int x, int y){
     switch(button){
     case GLUT_LEFT_BUTTON:
                         if(state == GLUT_DOWN){
                             if (n < 100) {
                                v = n++;
                                vert[v][0] = x;
                                 vert[v][1] = height - 1 - y;

                                // n++;
                                 rubberbanding = true;
                                 glutPostRedisplay();

                                 if (!closed) m = n;
                             }
                         }
                         else{
                                  rubberbanding = false;
                         }
                         break;
     }
}
void motion(int x, int y){
     if(rubberbanding){
                       vert[v][0] = x;
                       vert[v][1] = height - 1 - y;
                       glutPostRedisplay();
     }
}

void main(int argc, char** argv){
     glutInit(&argc, argv);
     glutInitDisplayMode(GLUT_RGB|GLUT_DOUBLE);
     glutInitWindowSize(width,height);
     glutInitWindowPosition(50,100);
     glutCreateWindow("Project 3");
     glClearColor(0.0,0.0,0.0,0.0);
     glColor3f( 1, 1, 0);
     glMatrixMode(GL_PROJECTION);
     glLoadIdentity();
     gluOrtho2D(0, width, 0, height);
     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
     glutDisplayFunc(display);
     glutKeyboardFunc(keyboard);
     glutMouseFunc(mouse);
     glutPassiveMotionFunc(mousemove);
     glutMotionFunc(motion);
     glutMainLoop();
}

When I run the program in Visual Studio, I can draw the polygon, and I can specify

points, but for some reason all the points appear red. If anyone has any ideas on how to fix this, it would be greatly appreciated.

jmac
  • 79
  • 9
  • did you check if your `inpoly` function work? can be simply done by `cout` or debugger. – apple apple Nov 19 '18 at 03:10
  • That is where my problem is, its not working right. And im not sure how to fix it. – jmac Nov 19 '18 at 03:33
  • so the rendering part is all right? – apple apple Nov 19 '18 at 03:34
  • Im not sure what you mean by the 'rendering part'. Im pretty sure its the inpoly function that isnt working properly. When i use cout in the inpoly function to output the final angle, I get a continuous stream of random decimals. – jmac Nov 19 '18 at 03:42
  • I actually think I was able to figure it out. Only thing is that all the colors change when I create a new point. Do you know of anyway that I can stop all the colors from changing when I create a new point? – jmac Nov 19 '18 at 05:07

1 Answers1

2

Probably your error is that acos returns in radians, and you're testing if the sum equals 360 degrees.

Also, you shouldn't compare doubles that way, since that calculation is probably adding rounding error in each sum. See here for more information.

Guille
  • 343
  • 2
  • 9
  • I completely forgot that acos returns in radians, good catch. Unfortunately, my program still isnt working the way I want it too. I think my `inpoly` function is still messed up but im not sure how to fix it. – jmac Nov 19 '18 at 04:44
  • I actually think I was able to figure it out. Only thing is that all the colors change when I create a new point. Do you know of anyway that I can stop all the colors from changing when I create a new point? – jmac Nov 19 '18 at 05:07