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