画Bezier曲线:鼠标获取、拖动控制点

您所在的位置:网站首页 opengl画曲线算法 画Bezier曲线:鼠标获取、拖动控制点

画Bezier曲线:鼠标获取、拖动控制点

2024-06-10 23:31| 来源: 网络整理| 查看: 265

本文是在前一篇绘制Bezier曲线的基础上加上了鼠标获取、拖动控制点的功能。主要练习OpenGL的鼠标操作。

鼠标操作内容转载自OpenGL鼠标操作 - 知乎 (zhihu.com)

鼠标操作函数为:

glutMouseFunc(mouse_hit); glutMotionFunc(mouse_move);

鼠标操作函数括号里的mouse_hit,mouse_move的内容自己编写,当然名称也可以自定义。

 

mouse_hit函数:

void mouse_hit(int button, int state, int x, int y)

button:表示鼠标操作的是左键(GLUT_LEFT_BUTTON)、中键(GLUT_MIDDLE_BUTTON)、右键(GLUT_RIGHT_BUTTON),也可分别用整数0、1、2表示。

state:表示鼠标按键状态,包括按下(GLUT_DOWN)和抬起(GLUT_UP),也可分别用整数0和1表示

x,y:表示鼠标的坐标位置。

根据上述内容,鼠标点击函数只能获取x,y,所以我们也只能在二维平面里获取控制点、绘制Bezier曲线了。

 

mouse_move函数:

void mouse_move(int x, int y)

x,y:表示鼠标坐标位置。

 

注意设置一些全局变量来保存鼠标和控制点的信息:

int i = 0;//目前画出的控制点的个数 int total = 0;//控制点点的总个数 int mposition = 0;//移动的控制点在数组中的下标 int sta = 0;//鼠标是否按下 int button_kind = -1;//鼠标左右中键

 

利用以上两个鼠标函数和之前的Bezier绘制函数来实现功能:点击左键定位控制点,点击右键表示控制点绘制结束,绘制Bezier曲线。代码如下:

#include #include #include typedef struct { int length; int* arr; }intArray;//系数坐标 typedef struct { float x, y; } point2D;//存储二维坐标 typedef struct { int length; point2D* arr; }pointArray2D; int i = 0;//画出的点的个数 int total = 0;//点的总个数 int mposition = 0;//移动的点在数组中的下标 int sta = 0;//鼠标是否按下 int button_kind = -1;//鼠标左右中键 pointArray2D ctrlPts2D_; point2D ctrlPts2D[7] = { }; //鼠标点击(左键确定控制点,右键表示绘制完成) void mouse_hit(int button, int state, int x, int y) { button_kind = button; switch (button) { case GLUT_LEFT_BUTTON: if (state == GLUT_DOWN) {//如果左键按下时 //将鼠标位置记录到控制点坐标数组中 if (total == 0) {//控制点还未绘制完成时 ctrlPts2D[i].x = (float)x / 100; ctrlPts2D[i].y = (float)y / 100; i++; } else if (total != 0) {//要改变控制点的坐标时 for (int j = 0; j < total; j++) { if ((fabs(ctrlPts2D[j].x - ((double)x / 100)) < 0.1) && (fabs(ctrlPts2D[j].y - ((double)y / 100)) < 0.1)) { mposition = j; ctrlPts2D[mposition].x = (float)x / 100; ctrlPts2D[mposition].y = (float)y / 100; sta = 1; } } } } else if (state = GLUT_UP ) {//如果左键从按下到抬起(结束移动控制点 ctrlPts2D[mposition].x = (float)x / 100; ctrlPts2D[mposition].y = (float)y / 100; mposition = -1; sta = 0; } break; case GLUT_RIGHT_BUTTON: total = i; } } //鼠标移动(拖动控制点以改变曲线形状) void mouse_move(int x, int y) { if (sta == 1) { float movex = (float)x / 100; float movey = (float)y / 100; ctrlPts2D[mposition].x = movex; ctrlPts2D[mposition].y = movey; } } //确定控制点,画出控制点和直线 void mouseclick() { //左键绘制控制点,右键或者中键控制点消失 if (button_kind == GLUT_LEFT_BUTTON) { glPointSize(10); glBegin(GL_POINTS); glColor3f(0.0f, 0.0f, 1.0f); for (int j = 0; j < i; j++) { glVertex2f(ctrlPts2D[j].x, ctrlPts2D[j].y); } glEnd(); if ((total == 0) || (total==i)) { glBegin(GL_LINE_STRIP); for (int j = 1; j < i; j++) { glVertex2f(ctrlPts2D[j - 1].x, ctrlPts2D[j - 1].y); glVertex2f(ctrlPts2D[j].x, ctrlPts2D[j].y); } } glEnd(); } } void deCasteljau(pointArray2D& ctrlPts, int precision) { int n = total; if (n < 2)return; float* xarray = new float[n - 1]; float* yarray = new float[n - 1]; float x = ctrlPts.arr[0].x; float y = ctrlPts.arr[0].y; for (int k = 0; k


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3