确定用户指定的点是否在2D多边形内

时间:2018-11-19 02:59:11

标签: c++ opengl visual-studio-2015 polygon

我已经做过一些研究,并且如果顶点和点是预先确定的,则有很多方法可以这样做here。但是,就我而言,一切都由用户指定。我整理的代码(在其他人的帮助下)允许用户创建多边形并放置点。我编写了函数来尝试创建从点到顶点的向量,然后计算角度。如果是360,它应该在里面并且应该被涂成绿色。否则它应该在外面红色。

这是我一直在努力的工作,但是我似乎无法弄清楚: (编辑:包括我的全部代码)

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

点,但是由于某些原因所有点都显示为红色。如果有人对如何解决此问题有任何想法,将不胜感激。

1 个答案:

答案 0 :(得分:2)

可能是您的错误是acos以弧度返回,并且您正在测试总和是否等于360度。

此外,您不应以这种方式比较双精度数,因为该计算可能会在每个和中增加舍入误差。有关更多信息,请参见here