1. 程式人生 > >【OpenGL】中點法畫橢圓

【OpenGL】中點法畫橢圓

仍然可以看成是Bresenham演算法的一個應用,書上叫它“中點法”(原因是當我們不能確定取哪個座標的時候,就用兩個待定的座標的中點代入方程來幫助判斷)。

Bresenham演算法歸根到底要解決的就是“下一個點怎麼選更精確”這個問題,解決的套路是:

1)先給出一個判別函式,這個函式就是所要畫的曲線的方程式;

2)求解這個判別函式的遞推式;

2)總是從畫素點更密集的方向開始選點(方便起見從x開始,每次加1);

3)判斷下一個點x+1對應的理論座標和實際座標的差距,選差距小的作為y座標;

4)不斷重複3),直到達到臨界條件(通常是斜率,一般只需要考慮斜率小於1的情形,其他對稱解決)

橢圓的思路是一樣的,只是方程更復雜,所以推導過程更繁瑣一點:


注意這裡是用斜率來確定臨界點,隱函式求導可以得到k=-2x^2Ry/2y^2Rx。每次的分子分母也可以用增量的方式來計算。

最終的程式碼:

//中心點法畫橢圓

#include<iostream>
using namespace std;

#include<windows.h>
#include<gl/glut.h>

/*函式申明*/
void myDisplay(void);//用來呼叫eclipseBres()
int round(const float x);
void setPixel(int x,int y);//畫點的函式
void symmetricPoints(int xc,int yc,int rx,int ry);//在對稱位置畫點
void changeSize(GLsizei w, GLsizei h);//視窗大小改變時呼叫的登記函式
void eclipseBres(int xc,int yc,int rx,int ry);//畫橢圓的主要函式

/*函式實現*/
void myDisplay(void){
	eclipseBres(120,120,50,100);
}

int round(const float x){
	return (x+0.5);
}

void setPixel(int x,int y){
	//使用OpenGL的glVertex2i來畫點
	glPointSize(2.0f);
	glBegin(GL_POINTS);
		glVertex2i(x,y);
	glEnd();
	glFlush();
}

void symmetricPoints(int xc,int yc,int rx,int ry){
	setPixel(xc+rx,yc+ry);
	setPixel(xc-rx,yc+ry);
	setPixel(xc+rx,yc-ry);
	setPixel(xc-rx,yc-ry);
}

void changeSize(GLsizei w, GLsizei h){
	//這個函式和OpenGL顯示有關,和演算法本身無關
    if(h==0)     
		h=1;
    glViewport(0,0,w,h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    if (w <= h)
        glOrtho(0.0f,250.0f,0.0f,250.0f*h/w,1.0,-1.0);
    else
        glOrtho(0.0f,250.0f*w/h,0.0f,250.0f,1.0,-1.0);
}

void eclipseBres(int xc,int yc,int rx,int ry){
	int x=0,y=ry;
	int rx2=rx*rx,ry2=ry*ry;
	int tworx2=2*rx2,twory2=2*ry2;
	int px=0,py=tworx2*y;
	int p=round(ry2-rx2*ry+0.25*rx2);
	symmetricPoints(xc,yc,x,y);
	while(py>px){
		x++;
		px+=twory2;
		if(p<0)
			p+=ry2+px;
		else{
			y--;
			py-=tworx2;
			p+=ry2+px-py;
		}
		symmetricPoints(xc,yc,x,y);
	}
	//region2
	p=round(ry2*(x+0.5)*(x+0.5)+rx2*(y-1)*(y-1)-rx2*ry2);
	while(y>0){
		y--;
		py-=tworx2;
		if(p>0)
			p+=rx2-py;
		else{
			x++;
			px+=twory2;
			p+=rx2-py+px;
		}
		symmetricPoints(xc,yc,x,y);
	}
}

int main(int argc,char* argv[]){
	//OPenGL顯示圖形的框架
	glutInit(&argc,argv);
	glutInitDisplayMode(GLUT_RGB|GLUT_SINGLE);
	glutInitWindowPosition(200,200);
	glutInitWindowSize(400,400);
	glutCreateWindow("練習");
	glutDisplayFunc(&myDisplay);
	glutReshapeFunc(changeSize);
	glutMainLoop();
	return 0;
}
執行效果:



相關推薦

OpenGL中點橢圓

仍然可以看成是Bresenham演算法的一個應用,書上叫它“中點法”(原因是當我們不能確定取哪個座標的時候,就用兩個待定的座標的中點代入方程來幫助判斷)。 Bresenham演算法歸根到底要解決的就是“下一個點怎麼選更精確”這個問題,解決的套路是: 1)先給出一個判別函式,

OpenGL中點圓、橢圓生成演算法

中點圓生成演算法 因為圓具有對稱性,一次性可以畫8個點 中點圓生成演算法-C++程式碼 #include<GL\glut.h> #include<iostream> #include<cmath> using

OpenGL使用DDA演算法

DDA(數字微分分析儀...好高大上的樣子)演算法其實就是利用直線方程來生成直線的演算法,給定起點(x0,y0)和終點(xEnd,yEnd),這條直線就唯一確定了,它的斜率是k=(yEnd-y0)/(xEnd-x0)。對於x方向我們取增量為1,那麼下一個x值,即xi+1=x

OpenGLShader實例分析(七)- 雪花飄落效果

mouse llb cto 接下來 pix lan details effect art 轉發請保持地址:http://blog.csdn.net/stalendp/article/details/40624603 研究了一個雪花飄落效果。感覺挺不錯的。分享給大家,效

OPenGLopengl 64位 配置

技術 添加 os x 源代碼 lar ebs 庫文件 定義 software 1.GLEW The OpenGL Extension Wrangler Library (GLEW) is a cross-platform open-source C/C++ extensio

OpenGLShader實例分析(九)- AngryBots中的主角受傷特效

spa 2.7 imp ttext pro tint shader 作用 負責 轉發請保持地址:http://blog.csdn.net/stalendp/article/details/40859441 AngryBots是Unity官方的一個非常棒的樣例。非常有研究

技巧競賽中對拍程序的寫法

定向 軟件 err 出錯 OS 進行 小數據 goto 隨機數 在競賽過程中一個對拍程序可以幫你排除許多錯誤, 如果擔心自己寫的正解被一些小數據卡掉, 我們通常會寫個對拍程序來檢查正解的正確性, 通過大量數據觀察正解與暴力的輸出是否相同。 我們首先拿出我們寫的可能會超時但是

OpenGLLNK1104 無法打開文件“freeglutd.lib”

lease 編譯 idt pen spa bubuko 預處理器 無法打開 解決 新建的OpenGL程序編譯時經常會出現[LNK1104 無法打開文件“freeglutd.lib”]問題,如果freeglutd.lib確實放到了正確的路徑下,通常可以通過添加“NDEBUG”

OpenGL平移變換矩陣

AC pan sel .com light alt style 分享圖片 平移 摘自:http://ogldev.atspace.co.uk/www/tutorial06/tutorial06.html 以下等式計算平移:等式左邊,左項為旋轉平移矩陣M,右項為原坐標P,

leetcode題3 無重復字符的最長子串

sim bcb IT wid VM str longest solid eat 問題   給定一個字符串,找出不含有重復字符的最長子串的長度。 示例: 給定 "abcabcbb" ,沒有重復字符的最長子串是 "abc" ,那麽長度

的時間復雜度

語句 期望 cmp sum 去掉 函數 要求 rcm 實例 定義:如果一個問題的規模是n,解這一問題的某一算法所需要的時間為T(n),它是n的某一函數 T(n)稱為這一算法的“時間復雜性”。當輸入量n逐漸加大時,時間復雜性的極限情形稱為算法的“漸近時間復雜性”。我們常用大O

原始碼牛頓求解實值函式的根

示例:[ x, ex ] = newton( ‘exp(x)+x’, ‘exp(x)+1’, 0, 0.5*10^-5, 10 ) f:輸入函式 df:輸入函式的導數 x0:函式根的初值估計 tol:誤差容忍度 namx:求解最大迭代次數 x:求解輸出的近似根 e

OpenGL-010 使用shader

【OpenGL】-010 使用shader 文章目錄 【OpenGL】-010 使用shader 1. OpenGL中的shader 2. 示例 2. shader的使用流程 1. OpenGL中的shade

OpenGL-009 GLUT中處理鍵盤滑鼠事件

【OpenGL】-009 GLUT中處理鍵盤滑鼠事件   鍵盤和滑鼠是GUI程式獲取使用者輸入的重要方式,在windows程式中,通過WM_KEY_DOWN/WM_KEY_UP/WM_LBUTTONDOWN/WM_RBUTTONDOWN等訊息的響應,使用者可以方便的處理鍵盤滑鼠的輸入。在

OpenGL-008 GLUT中的定時器

【OpenGL】-008 GLUT中的定時器   定時器是視窗程式中的一個重要功能,用於按照固定的時間間隔之後執行某些特定動作。在window程式中,有WM_TIMER訊息進行響應。在使用GLUT進行視窗管理的程式中,如何進行定時器操作? 文章目錄 【OpenG

OpenGL-007 在視窗上顯示一個三角形

【OpenGL】-007 在視窗上顯示一個三角形 文章目錄 【OpenGL】-007 在視窗上顯示一個三角形 1. 在視窗上顯示一個三角形 2. 效果 3. 備註 1. 在視窗上顯示一個三角形 /* Fi

最簡單的 UBO(Uniform Buffer Object) OpenGLGLSL

一、引入 Uniform Buffer Object / Uniform Block 的 原因 1)  如果程式涉及了多個 Shader 程式,而且它們使用同一個Uniform變數,那麼你就需要為每個 Shader 程式單獨管理它們。當一個程式被連結時,OpenGL 會自動生成

P1865求素數+區間!

#include<bits/stdc++.h> using namespace std; const int maxn=1000010; bool a[maxn]; int primesum[maxn]; void printPrimes(){ memset(a,true,size

LeetCode回溯 backtracking(共39題)

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica } 【10】Regular Expression Matching  【17】Letter Combinations of a Phone Number  【

JAVA二分查詢指定元素的下標

如果,我們要在一個數組中查詢某個指定的元素,可以使用二分法,從而大大降低查詢效率,前提是所給定的陣列是已經排序的; 下面是一個小小的例子 public class BinarySearch{ publ