openGL 入门demo, 三维空间随机数据拟合直线


#include
#include
#include
#include
#include //Windows的头文件
#include "GL/glut.h"//包含OpenGL实用库
#include
#include
#include

#define Randmod(x) rand()%x
//#include
//#include
using namespace Eigen;
using namespace cv;
using namespace std;

#define M_PI 3.1415926
#define SOLID 1
#define WIRE 2

int moveX, moveY;
int spinX = 0;
int spinY = 0;
int des = 0;

void glutInitFunc();
void display();
void drawCordinateFunc();
void drawPoints();
void drawLinesGrid();
/*
    name : kenny adelaide
    company: 
    date time :2021/7/19
    Description: 
*/


//鼠标点击事件
void mouseClick(int btn, int state, int x, int y) {
    moveX = x;
    moveY = y;
    GLfloat ambient[] = { (float)rand() / RAND_MAX, (float)rand() / RAND_MAX, (float)rand() / RAND_MAX, 0.1 };
    //设置环境光
    glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
    //启用光源
    glEnable(GL_LIGHT0);
}
//键盘事件
void keyPressed(unsigned char key, int x, int y) {
    switch (key) {
    case 'a':
        spinX -= 2;
        break;
    case 'd':
        spinX += 2;
        break;
    case 'w':
        des += 2;
        break;
    case 's':
        des -= 2;
        break;
    }
    glutPostRedisplay();
}
// 鼠标移动事件 
void mouseMove(int x, int y) {
    int dx = x - moveX;
    int dy = y - moveY;
    printf("dx;%dx,dy:%dy\n", dx, dy);
    spinX += dx;
    spinY += dy;
    glutPostRedisplay();
    moveX = x;
    moveY = y;
}
void reshape(int w, int h) {
    //定义视口大小
    glViewport(0, 0, (GLsizei)w, (GLsizei)h);
    //投影显示
    glMatrixMode(GL_PROJECTION);
    //坐标原点在屏幕中心
    glLoadIdentity();
    //操作模型视景
    gluPerspective(60.0, (GLfloat)w / (GLfloat)h, 1.0, 20.0);
    glMatrixMode(GL_MODELVIEW);
}


int main(int argc, char** argv)
{
    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

    /*
    * ================================================================
        opengL 初始化 一个坐标系
    */

    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
    glutInitWindowSize(1500, 1500);
    glutInitWindowPosition(50, 50);
    glutCreateWindow(argv[0]);

    glutInitFunc();
    glutDisplayFunc(display);


    glutReshapeFunc(reshape);
    //鼠标点击事件,鼠标点击或者松开时调用
    glutMouseFunc(mouseClick);
    //鼠标移动事件,鼠标按下并移动时调用
    glutMotionFunc(mouseMove);
    //键盘事件
    glutKeyboardFunc(keyPressed);
    //循环
    glutMainLoop();
    /*
    ===================================================================
    */


    return 0;
}

// 画点
void drawPoints()
{
    glClear(GL_COLOR_BUFFER_BIT);
    glColor3f(0.0, 1.0, 0.0);

    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);


    // 定义模板的原点位置
    GLfloat MB_ORIGINAL_POIONT[3] = { 100,200,100 };
    int scaleSize = 4;
    double length = 80.4 * scaleSize;
    double height = 72.4 * scaleSize;
    double width = 20 * scaleSize;

    //1.0 构建一个正方体
    GLfloat vertex_list_cub[][3] =
    {
        MB_ORIGINAL_POIONT[0],MB_ORIGINAL_POIONT[1],MB_ORIGINAL_POIONT[2],
        MB_ORIGINAL_POIONT[0] + length,MB_ORIGINAL_POIONT[1],MB_ORIGINAL_POIONT[2],
        MB_ORIGINAL_POIONT[0],MB_ORIGINAL_POIONT[1] + height,MB_ORIGINAL_POIONT[2],
        MB_ORIGINAL_POIONT[0] + length,MB_ORIGINAL_POIONT[1] + height,MB_ORIGINAL_POIONT[2],

        MB_ORIGINAL_POIONT[0],MB_ORIGINAL_POIONT[1],MB_ORIGINAL_POIONT[2] + width,
        MB_ORIGINAL_POIONT[0] + length,MB_ORIGINAL_POIONT[1],MB_ORIGINAL_POIONT[2] + width,
        MB_ORIGINAL_POIONT[0],MB_ORIGINAL_POIONT[1] + height,MB_ORIGINAL_POIONT[2] + width,
        MB_ORIGINAL_POIONT[0] + length,MB_ORIGINAL_POIONT[1] + height,MB_ORIGINAL_POIONT[2] + width
    };

    GLint index_list[][4] = {
        0, 2, 3, 1,
        0, 4, 6, 2,
        0, 1, 5, 4,
        4, 5, 7, 6,
        1, 3, 7, 5,
        2, 6, 7, 3,
    };


    // 绘制的时候代码很简单
    glBegin(GL_QUADS);
    for (int i = 0; i < 6; ++i)         // 有六个面,循环六次
        for (int j = 0; j < 4; ++j)     // 每个面有四个顶点,循环四次
            glVertex3fv(vertex_list_cub[index_list[i][j]]);
    glEnd();

    // 画一些小圆柱孔
    glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
    const int n = 300;
    const GLfloat R = 1.40f * scaleSize;
    glPointSize(1);
    glBegin(GL_POLYGON);
    GLfloat MB_ORIGINAL_POIONT_cuirve[3] = { MB_ORIGINAL_POIONT[0] + 10.2 * scaleSize,MB_ORIGINAL_POIONT[1] + 3.8 * scaleSize,MB_ORIGINAL_POIONT[2] };

    // 定义一个针孔位置矩阵,存放所有孔位置信息
    std::vector CURVE_POINTS;

    GLdouble InserPointDistance = 50;
    GLint count = 0;
    for (int k = 0; k < 13; k++)
    {
        for (int j = 0; j < 13; j++)
        {
            for (int i = 0; i < n; i++)
            {
                glColor3f(1.0f, 0.0f, 0.0f);
                glVertex3f(R * cos(2 * M_PI / n * i) + MB_ORIGINAL_POIONT_cuirve[0] + 5 * scaleSize * k, -R * sin(2 * M_PI / n * i) + MB_ORIGINAL_POIONT_cuirve[1] + 5 * scaleSize * j, MB_ORIGINAL_POIONT_cuirve[2] + 1);
                glVertex3f(R * cos(2 * M_PI / n * i) + MB_ORIGINAL_POIONT_cuirve[0] + 5 * scaleSize * k, -R * sin(2 * M_PI / n * i) + MB_ORIGINAL_POIONT_cuirve[1] + 5 * scaleSize * j, MB_ORIGINAL_POIONT_cuirve[2] + (width - 1));

                GLdouble x = R * cos(2 * M_PI / n * i) + MB_ORIGINAL_POIONT_cuirve[0] + 5 * scaleSize * k;
                GLdouble y = -R * sin(2 * M_PI / n * i) + MB_ORIGINAL_POIONT_cuirve[1] + 5 * scaleSize * j;
                GLdouble z = MB_ORIGINAL_POIONT_cuirve[2] - 20;

                Point3f p(x, y, z);
                CURVE_POINTS.push_back(p);
            }
        }
    }
    glEnd();


    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

    // =======================================================创建拟合数据=============================================================
    // 1.0 插入针
    // 设置线段的宽度
    glLineWidth(1.0);

    glBegin(GL_LINES); //画线

    int PosationState = 15;
    int pointLength = 300;
    /*for (int i = 0; i < CURVE_POINTS.size(); i++)
    {*/
    glColor3f(0.5, 0.5, 0.5);
    glVertex3f(CURVE_POINTS[PosationState].x, CURVE_POINTS[PosationState].y, CURVE_POINTS[PosationState].z);
    glVertex3f(CURVE_POINTS[PosationState].x, CURVE_POINTS[PosationState].y, CURVE_POINTS[PosationState].z + pointLength);
    /*}*/
    glEnd();

    glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
    GLfloat x, y, z, angle; // 存储坐标和角度
    // 对所有剩余的点只调用一次

    glPointSize(3);
    glBegin(GL_TRIANGLES);

    vector Points(100);
    for (int i = 10; i < pointLength; i += 6)
    {
        Point3f p(CURVE_POINTS[PosationState].x + Randmod(10), CURVE_POINTS[PosationState].y + Randmod(10), CURVE_POINTS[PosationState].z + Randmod(10) + i);
        Points.push_back(p);
        // glColor3f(0.0f + i * 0.01, 0.0f + i * 0.01, 0.0f + i * 0.01);
        glColor3f(0.3, 0.7, 0.7);
        glVertex3f(p.x, p.y, p.z);
    }

    // line 中前三个为点斜式方程中的方向向量, 后三个为直线上的一点
    cv::Vec6f line;
    cv::fitLine(Points, line, cv::DIST_L1, 0, 0.01, 0.01);
    /*glColor3f(1.0, 0.0, 0.0);
    glVertex3f(line[3], -line[4], line[5]);
    glEnd();
    glFlush();*/

    // 通过Line 参数 求出两个点的坐标,通过两个点的坐标画一条直线
    // 取一个固定的值(x,y,z)三者中任意一项都可以,分别计算出另外两个的取值
    // x=100;
    GLfloat x1 = CURVE_POINTS[PosationState].x;  // x取拟合数据的x起始点
    GLfloat y1 = ((x1 - line[3]) / line[0]) * line[1] + line[4];
    GLfloat z1 = ((y1 - line[4]) / line[1]) * line[2] + line[5];

    cv::Point3f p1(x1, y1, z1);
    cv::Point3f p2(line[3], line[4], line[5]);
    glColor3f(1.0, 0.0, 0.0);

    glBegin(GL_LINES);
    glVertex3f(p1.x, p1.y, p1.z);
    glVertex3f(p2.x, p2.y, p2.z);
    glEnd();

    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

    //============================================ 画体模==============================================
    // 定义模板的原点位置
    GLfloat MB_ORIGINAL_MODEL[3] = { 100,200,370 };
    int scaleSize_MODEL = 2;
    double length_MODEL = 80.4 * scaleSize_MODEL;
    double height_MODEL = 72.4 * scaleSize_MODEL;
    double width_MODEL = 50 * scaleSize_MODEL;

    //1.0 构建一个正方体
    GLfloat vertex_list_cub_MODEL[][3] =
    {
        MB_ORIGINAL_MODEL[0],MB_ORIGINAL_MODEL[1],MB_ORIGINAL_MODEL[2],
        MB_ORIGINAL_MODEL[0] + length_MODEL,MB_ORIGINAL_MODEL[1],MB_ORIGINAL_MODEL[2],
        MB_ORIGINAL_MODEL[0],MB_ORIGINAL_MODEL[1] + height_MODEL,MB_ORIGINAL_MODEL[2],
        MB_ORIGINAL_MODEL[0] + length_MODEL,MB_ORIGINAL_MODEL[1] + height_MODEL,MB_ORIGINAL_MODEL[2],

        MB_ORIGINAL_MODEL[0],MB_ORIGINAL_MODEL[1],MB_ORIGINAL_MODEL[2] + width_MODEL,
        MB_ORIGINAL_MODEL[0] + length_MODEL,MB_ORIGINAL_MODEL[1],MB_ORIGINAL_MODEL[2] + width_MODEL,
        MB_ORIGINAL_MODEL[0],MB_ORIGINAL_MODEL[1] + height_MODEL,MB_ORIGINAL_MODEL[2] + width_MODEL,
        MB_ORIGINAL_MODEL[0] + length_MODEL,MB_ORIGINAL_MODEL[1] + height_MODEL,MB_ORIGINAL_MODEL[2] + width_MODEL
    };

    GLint index_list_MODEL[][4] = {
        0, 2, 3, 1,
        0, 4, 6, 2,
        0, 1, 5, 4,
        4, 5, 7, 6,
        1, 3, 7, 5,
        2, 6, 7, 3,
    };


    // 绘制的时候代码很简单
    glBegin(GL_QUADS);
    for (int i = 0; i < 6; ++i)         // 有六个面,循环六次
        for (int j = 0; j < 4; ++j)     // 每个面有四个顶点,循环四次
        {
            glColor3f(0.0, 1.0, 0.0);
            glVertex3fv(vertex_list_cub_MODEL[index_list_MODEL[i][j]]);
        }

    glEnd();

    //=============================================画三个病灶============================================
    GLdouble radius = 5 * scaleSize;
    glPushMatrix();
    glColor3f(0.0, 0.0, 1.0);
    glTranslated(CURVE_POINTS[PosationState].x + 100, CURVE_POINTS[PosationState].y + 100, CURVE_POINTS[PosationState].z + pointLength + 50);
    glutSolidSphere(radius, 10, 10);
    glPopMatrix();

    glPushMatrix();
    glColor3f(0.0, 1.0, 0.0);
    glTranslated(CURVE_POINTS[PosationState].x + 80, CURVE_POINTS[PosationState].y + 80, CURVE_POINTS[PosationState].z + pointLength + 20);
    glutSolidSphere(radius, 20, 20);
    glPopMatrix();

    glPushMatrix();
    glColor3f(1.0, 0.0, 0.0);
    glTranslated(CURVE_POINTS[PosationState].x + 60, CURVE_POINTS[PosationState].y + 60, CURVE_POINTS[PosationState].z + pointLength + 30);
    glutSolidSphere(radius, 15, 15);
    glPopMatrix();


    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
}


void drawCordinateFunc()
{

    glViewport(0, 0, 1500, 1500);

    //设置投影效果//
    glPushMatrix();
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(-1500, 1500, -1500, 1500, -1500, 1500); //指定了一个正方体区域,在这个区域内的图形才能正常显示

    glPopMatrix();

    glRotated(spinX, 0, 1, 0);
    glRotated(spinY, 1, 0, 0);
    glTranslated(0, 0, des);


    //设置模型视图矩阵,开始画图//
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    gluLookAt(0, 6, 0, 0, 0, 0, 0, 0, 1); //从(0,2,0)位置看向原点,z轴向上
    //第二,考虑到实际应用中我们需要对圆环进行旋转,那坐标系也应该进行旋转,这样才能一一对应上。

    glRotatef(-45, 1, 0, 0);
    glRotatef(-45, 0, 1, 0);
    glRotatef(-45, 0, 0, 1);

    const int AXES_LEN = 1500;
    const int ARROW_LEN = 5;
    const int ARROW_RADIUS = 8;

    GLUquadricObj* objCylinder = gluNewQuadric();
    glPushMatrix();
    glColor3f(1.0f, 1.0f, 1.0f);
    glutSolidSphere(0.25, 20, 20);
    glPopMatrix();


    glPushMatrix();
    glColor3f(1.0f, 0.0f, 0.0f);
    glutSolidSphere(0.25, 6, 6);
    gluCylinder(objCylinder, 1, 1, AXES_LEN, 10, 5); //Z
    glTranslatef(0, 0, 0);
    gluCylinder(objCylinder, ARROW_RADIUS, 0, ARROW_LEN, 10, 5); //z arrow
    glPopMatrix();
    glRasterPos3f(0, 0, AXES_LEN);
    glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, 'Z');

    /*glRasterPos3f(10, 10, 10);
    glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, 'O(W)');*/

    glPushMatrix();
    glColor3f(0.0f, 1.0f, 0.0f);
    glRotatef(270, 1.0, 0.0, 0.0);
    gluCylinder(objCylinder, 1, 1, AXES_LEN, 10, 5); //Y
    glTranslatef(0, 0, 0);
    gluCylinder(objCylinder, ARROW_RADIUS, 0, ARROW_LEN, 10, 5); //Y arrow
    glPopMatrix();
    glRasterPos3f(0, AXES_LEN, 0);
    glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, 'Y');


    glPushMatrix();
    glColor3f(0.0f, 0.0f, 1.0f);
    glRotatef(90, 0.0, 1.0, 0.0);
    gluCylinder(objCylinder, 1, 1, AXES_LEN, 10, 5); //X
    glTranslatef(0, 0, 0);
    gluCylinder(objCylinder, ARROW_RADIUS, 0, ARROW_LEN, 10, 5); //X arrow
    glPopMatrix();

    glRasterPos3f(AXES_LEN, 0, 0);
    glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, 'X');


    //==================================绘制坐标系刻度=====================================

    //for (int i = 1; i <15; i++)
    //{    
    //    char * value = std::to_string(i);
    //    glColor3f(1.0f, 0.0f, 0.0f);
    //    glRasterPos3f(0.0f, 0.0f, 0.0f);
    //    //glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, i*100);
    //    glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, value);
    //    //glCallLists(20, GL_UNSIGNED_BYTE, &value);
    //}
}

void display()
{


    /*画网格*/
    drawLinesGrid();

    drawCordinateFunc();
    /*绘制三维坐标系*/
    glutSwapBuffers();
}

void glutInitFunc()
{
    //定义光源的颜色和位置
    GLfloat ambient[] = { 0.5, 0.8, 0.1, 0.1 };
    GLfloat diffuse[] = { 1.0, 1.0, 1.0, 1.0 };
    GLfloat position[] = { -80.0, 50.0, 25.0, 1.0 };
    //选择光照模型
    GLfloat lmodel_ambient[] = { 0.4, 0.4, 0.4, 1.0 };
    GLfloat local_view[] = { 0.0 };
    glColor3f(0.0, 0.0, 0.0);
    glShadeModel(GL_SMOOTH);
    //设置环境光
    //glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
    //设置漫射光
    //glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
    //设置光源位置
    //glLightfv(GL_LIGHT0, GL_POSITION, position);
    //glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
    //glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER, local_view);
    //启动光照
    //glEnable(GL_LIGHTING);
    //启用光源
    //glEnable(GL_LIGHT0);
}

void drawLinesGrid()
{
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glEnable(GL_BLEND);
    glEnable(GL_POINT_SMOOTH);                   //设置反走样
    glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);       //设置反走样
    glEnable(GL_LINE_SMOOTH);
    glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
    glEnable(GL_POLYGON_SMOOTH);
    glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);


    drawPoints();


    int distance = 100;
    int length = 10000;
    int number = length / 10;
    /*for (int i = 1; i < number; i++)
    {
        glBegin(GL_LINES);
        glVertex3i((i - 1) * distance, 0, 0);
        glVertex3i((i - 1) * distance, -length, 0);
        glEnd();


        glBegin(GL_LINES);
        glVertex3i(0, -(i - 1) * distance, 0);
        glVertex3i(length, -(i - 1) * distance, 0);
        glEnd();
    }

    for (int i = 1; i < number; i++)
    {
        glBegin(GL_LINES);
        glVertex3i((i - 1) * distance, 0, 0);
        glVertex3i((i - 1) * distance, 0, length);
        glEnd();

        glBegin(GL_LINES);
        glVertex3i(0, 0, (i - 1) * distance);
        glVertex3i(length, 0, (i - 1) * distance);
        glEnd();
    }

    for (int i = 1; i < number; i++)
    {

        glBegin(GL_LINES);
        glVertex3i(0, (i - 1) * distance, 0);
        glVertex3i(0, (i - 1) * distance, length);
        glEnd();

        glBegin(GL_LINES);
        glVertex3i(0, 0, (i - 1) * distance);
        glVertex3i(0, -length, (i - 1) * distance);
        glEnd();
    }*/

    /*画坐标轴刻度*/
    /*for (int i = 0; i < 5; i++)
    {

        glRasterPos3f((int)i * 100, 0, 0);
        glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, 'i');


        glRasterPos3f(0, (int)i * 100, 0);
        glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, (int)i);

        glRasterPos3f(0, 0, (int)i * 100);
        glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, (int)i);
    }*/
}

openGL 入门demo, 三维空间随机数据拟合直线_第1张图片

 

你可能感兴趣的:(openGL,三维坐标系,三维空间点斜式数据拟合)