【计算机图形学 】绘制椭圆 | OpenGL+鼠标交互
生活随笔
收集整理的這篇文章主要介紹了
【计算机图形学 】绘制椭圆 | OpenGL+鼠标交互
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
文章目錄
- 其他計算機圖形學實驗
- 前言
- 1.輔助畫橢圓算法
- 2.橢圓的中點算法(兩種)
- 3.改變鼠標動作響應函數
- 4. 完整代碼
- 5. 總結
其他計算機圖形學實驗
傳送門
前言
實現繪制橢圓的中點算法,并和鼠標進行交互。
具體原理略過,會貼上完整代碼,可直接運行。
環境:
vs2019,OpenGL的庫(可以搜索如何用vs使用OpenGL的庫,可以使用vs自帶的插件或者其他方法,很方便)
要點:
1.設計畫橢圓的算法。設置橢圓中心和長短半軸的全局變量,通過鼠標得到全局變量的值,再傳入函數,進行橢圓的繪制。
2.改變鼠標點擊和鼠標拖拽的響應事件。
最終效果:
用鼠標在界面上拖拽,就會生成一個橢圓
1.輔助畫橢圓算法
由于橢圓的對稱性,我們只用畫出其四分之一即可。
//輔助畫橢圓算法 void OvalPoints(int x, int y, int x0, int y0) {glVertex2i(x + x0, y + y0);glVertex2i(-x + x0, y + y0);glVertex2i(x + x0, -y + y0);glVertex2i(-x + x0, -y + y0); }2.橢圓的中點算法(兩種)
方法一
/*橢圓的中點算法*/ void MidpointOval(int x0, int y0, int a, int b) {glClear(GL_COLOR_BUFFER_BIT);//清除窗口顯示內容glBegin(GL_POINTS);int x = 0, y = b;int a2 = a * a, b2 = b * b;float d1 = b2 + a2 * (0.25 - b);float d2 = b2 * (x + 0.5) * (x + 0.5) + a2 * (y - 1) * (y - 1) - a2 * b2;OvalPoints(x, y, x0, y0);int flag = 0; //分成上下部分的標志while (y>=0) {glBegin(GL_POINTS);OvalPoints(x, y, x0, y0);if (flag == 0) {if (a2*y<b2*x) flag = 1;}if (flag == 0) { //上半部分x++;if (d1 < 0) {d1 += b2 * (2 * x + 3);}else {y--;d1 += b2 * (2 * x + 3) + a2 * (2 - 2 * y);}}else { //下半部分y--;if (d2 >= 0) { //取正下方的點d2 += a2 * (3 - 2 * y);}else {x++;d2 += b2 * (2 * x + 2) + a2 * (3 - 2 * y);}}}glEnd();glFlush(); }方法二
/*橢圓的中點算法*/ void MidpointOval(int x0, int y0, int a, int b) {glClear(GL_COLOR_BUFFER_BIT);//清除窗口顯示內容glBegin(GL_POINTS);int x = 0, y = b;int a2 = a * a, b2 = b * b;float d1 = b2 + a2 * (0.25 - b);float d2 = b2 * (x + 0.5) * (x + 0.5) + a2 * (y - 1) * (y - 1) - a2 * b2;//float d2 = sqrt(b * (x + 0.5) + a * (y - 1)) - a * b;//glVertex2i(x0, y0);OvalPoints(x, y, x0, y0);while (a2*y>b2*x) { //注意這個判斷!!!glBegin(GL_POINTS);OvalPoints(x, y, x0, y0);x++;//++x;if (d1 < 0) {d1 += b2 * (2 * x + 3);}else {y--;//--y;d1 += b2 * (2 * x + 3) + a2 * (2 - 2 * y);}}x--; y++;while (y > 0) {y--;if (d2 >= 0) { //取正下方的點d2 += a2 * (3 - 2 * y);}else {x++;d2 += b2 * (2 * x + 2) + a2 * (3 - 2 * y);}glBegin(GL_POINTS);OvalPoints(x, y, x0, y0);}glEnd();glFlush(); }3.改變鼠標動作響應函數
//鼠標拖動 void dragmouse(int x, int y) {m1 = x;n1 = y;mm = (m0 + m1) / 2;nn = (n0 + n1) / 2;a = abs(m1 - m0) / 2;b = abs(n1 - n0) / 2;DrawOval(); //畫線glFlush(); }//鼠標監聽,畫點 void mymouse(int button, int state, int x, int y) {if (button == GLUT_LEFT_BUTTON && state == GLUT_UP) {m1 = x;n1 = y;mm = (m0 + m1) / 2;nn = (n0 + n1) / 2;a = abs(m1 - m0) / 2;b = abs(n1 - n0) / 2;printf("橢圓起始點坐標為:(%d,%d),長半軸為:%d,短半軸為:%d\n", m0, n0, a, b);DrawOval(); glFlush();}if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) { //按下鼠標,是起點m0 = x;n0 = y;} }4. 完整代碼
#include<cstdio> #include<cstdlib> #include<cmath> #include<gl\glut.h> using namespace std;int m0, n0, m1, n1;//聲明全局變量 int mm, nn; //橢圓的中心點 int a, b; //橢圓的長半軸和短半軸 int winwidth = 800, winheight = 500;//窗口長寬 void DrawOval(); //實際上畫圓的函數 void MidpointOval(int, int, int, int); //橢圓的中點算法//實際上畫圓的函數 void DrawOval() {MidpointOval(mm, nn, a, b); //橢圓的中點算法 }//輔助畫橢圓算法 void OvalPoints(int x, int y, int x0, int y0) {glVertex2i(x + x0, y + y0);glVertex2i(-x + x0, y + y0);glVertex2i(x + x0, -y + y0);glVertex2i(-x + x0, -y + y0); }/*橢圓的中點算法*/ void MidpointOval(int x0, int y0, int a, int b) {glClear(GL_COLOR_BUFFER_BIT);//清除窗口顯示內容glBegin(GL_POINTS);int x = 0, y = b;int a2 = a * a, b2 = b * b;float d1 = b2 + a2 * (0.25 - b);float d2 = b2 * (x + 0.5) * (x + 0.5) + a2 * (y - 1) * (y - 1) - a2 * b2;OvalPoints(x, y, x0, y0);/*方法一*/while (a2*y>b2*x) { //注意!!!glBegin(GL_POINTS);OvalPoints(x, y, x0, y0);x++;//++x;if (d1 < 0) {d1 += b2 * (2 * x + 3);}else {y--;//--y;d1 += b2 * (2 * x + 3) + a2 * (2 - 2 * y);}}x--; y++;while (y > 0) {y--;if (d2 >= 0) { //取正下方的點d2 += a2 * (3 - 2 * y);}else {x++;d2 += b2 * (2 * x + 2) + a2 * (3 - 2 * y);}glBegin(GL_POINTS);OvalPoints(x, y, x0, y0);}/*方法二*///int flag = 0; //分成上下部分的標志//while (y>=0) {// glBegin(GL_POINTS);// OvalPoints(x, y, x0, y0);// if (flag == 0) {// if (a2*y<b2*x) flag = 1;// }// if (flag == 0) { //上半部分// x++;// if (d1 < 0) {// d1 += b2 * (2 * x + 3);// }// else {// y--;// d1 += b2 * (2 * x + 3) + a2 * (2 - 2 * y);// }// }// else { //下半部分// y--;// if (d2 >= 0) { //取正下方的點// d2 += a2 * (3 - 2 * y);// }// else {// x++;// d2 += b2 * (2 * x + 2) + a2 * (3 - 2 * y);// }// }//}glEnd();glFlush(); }//鼠標拖動 void dragmouse(int x, int y) {m1 = x;n1 = y;mm = (m0 + m1) / 2;nn = (n0 + n1) / 2;a = abs(m1 - m0) / 2;b = abs(n1 - n0) / 2;DrawOval(); //畫線glFlush(); }//鼠標監聽,畫點 void mymouse(int button, int state, int x, int y) {if (button == GLUT_LEFT_BUTTON && state == GLUT_UP) {m1 = x;n1 = y;mm = (m0 + m1) / 2;nn = (n0 + n1) / 2;a = abs(m1 - m0) / 2;b = abs(n1 - n0) / 2;printf("橢圓起始點坐標為:(%d,%d),長半軸為:%d,短半軸為:%d\n", m0, n0, a, b);DrawOval(); glFlush();}if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) { //按下鼠標,是起點m0 = x;n0 = y;} }void init() {glClearColor(1, 1, 1, 1);//設置繪制窗口顏色為白色glClear(GL_COLOR_BUFFER_BIT);//清除窗口內容glPointSize(3.0f);//設置點的大小/*設置為投影類型模式和其他觀察參數*/glMatrixMode(GL_PROJECTION);glLoadIdentity();gluOrtho2D(0, winwidth, winheight, 0);glColor3f(0, 1, 1);//設置畫點的顏色 }int main(int argc, char** argv) {glutInit(&argc, argv);//初始化glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);//設置繪制模式glutInitWindowPosition(350, 200);//設置窗口出現的位置glutInitWindowSize(winwidth, winheight);//設置窗口大小glutCreateWindow("畫橢圓");//創建窗口init();glutDisplayFunc(DrawOval);//繪制回調函數,glut機制,它覺得需要重新繪制的時候就會執行glutMouseFunc(mymouse);//鼠標監聽回調函數glutMotionFunc(dragmouse);//鼠標拖動glutMainLoop(); }5. 總結
橢圓是在圓的基礎上進行改變,算法更難了一點。要注意橢圓從上半部分變到下半部分的判斷點。因為這個判斷點弄錯了,找了好久的bug都沒找出來
總結
以上是生活随笔為你收集整理的【计算机图形学 】绘制椭圆 | OpenGL+鼠标交互的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Windows 2008 R2 终端服务
- 下一篇: Stellarium(虚拟天文馆)