① 請問中點bresenham演算法畫圓與bresenham演算法畫圓有區別嗎
Bresenham演算法畫圓:
Bresenham演算法用來畫直線非常方便,但上次也說了,Bresenham演算法也可以用來顯示圓和其他曲線,只需要把直線方程改成圓方程或者其他曲線的方程就行,具體的推理過程就不演示了,大體跟直線的差不多!但由推算的結果可以看出,用Bresenham演算法來畫圓的確是不大明智的做法,要計算的步驟太多,計算速度比專門的畫圓方法慢很多!並且在斜率越大的地方像素的間距就越大,當然我們可以在畫某個像素之前先判斷一下這一點跟前面一點的連線的斜率,然後在適當的時候交換x、y的坐標,但這樣計算量必將增加!
直接給出Bresenham畫圓的代碼:
#include<gl/glut.h>
#include<math.h>
#include<stdio.h>
voiddraw_pixel(intix,intiy)
{
glBegin(GL_POINTS);
glVertex2i(ix,iy);
glEnd();
}
//intinlineround(constfloata){returnint(a+0.5);}
voidBresenham(intx1,inty1,intr,doublea,doubleb,doublec)/*圓心在(x1,y1),半徑為r的圓*/
{
glColor3f(a,b,c);
intdx=r;//intdy=abs(yEnd-y1);
//intp=2*dy-dx;
//inttwoDy=2*dy,twoDyMinusDx=2*dy-2*dx;
intx,y,d1,d2;
/*if(x1>xEnd)
{
x=xEnd;y=yEnd;
xEnd=x1;
}
else
{
x=x1;
y=y1;
}
*/
x=x1;
y=y1+r;
draw_pixel(x1,y1);
draw_pixel(x,y);//起始點裝入幀緩存,起始點是圓的最上面一點,然後按順時針來畫
while(x<=x1+dx)
{
d1=y1+sqrt(pow(r,2)-pow(x-x1,2));/*lower*/
x++;
d2=2*(y1+sqrt(pow(r,2)-pow(x-x1,2)))-2*d1-1;/*lower-upper*/
if(1)
{
y=d1;
draw_pixel(x,y);
draw_pixel(x,2*y1-y);
draw_pixel(2*x1-x,y);
draw_pixel(2*x1-x,2*y1-y);
}
else
{
y++;
//p+=twoDyMinusDx;
draw_pixel(x,y);
}
}
}
voiddisplay()
{
glClear(GL_COLOR_BUFFER_BIT);
Bresenham(250,250,200,0.0,0.0,1.0);
Bresenham(300,250,150,1.0,0.0,0.0);
Bresenham(200,250,150,0.0,1.0,0.0);
//Bresenham(250,300,150,0.8,0.4,0.3);
//Bresenham(250,200,150);
glFlush();
}
voidmyinit()
{
glClearColor(0.8,1.0,1.0,1.0);
//glColor3f(0.0,0.0,1.0);
glPointSize(1.0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0,500.0,0.0,500.0);
}
voidmain(intargc,char**argv)
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
glutInitWindowSize(500,500);
glutInitWindowPosition(200.0,200.0);
glutCreateWindow("CG_test_Bresenham_Circleexample");
glutDisplayFunc(display);
myinit();
glutMainLoop();
}
以下為程序運行效果:
中點畫圓:
用光柵畫圓的不足在上次已經用實例表示的很明白了,上次畫的那個圓怎麼都不能算滿意,雖然可以通過修改演算法來得到改善,但本來計算步驟就已經很多了,交換坐標重新計算將會大大增加計算機的就是負擔,為此我們採用另一種更加常用的畫圓演算法——中點畫圓演算法,之所以叫做「中點」畫圓演算法是由於它不是像Bresenham演算法那樣所繪像素不是(xk+1,yk)就是(xk+1,yk+1),而是根據這兩個點的中點來判斷是(xk+1,yk)還是(xk+1,yk-1)更接近於圓!
對於給定的半徑r和圓心(x0,y0),我們先計算圓心在原點(0,0)的點,然後將其平移到圓心(x0,y0)處即可,跟Bresenham演算法一樣,我們也可以藉助圓的高度對稱性來減少計算機的計算步驟,在這里我們可以先計算出八分之一圓的像素點,然後根據對稱性繪出其他點。這樣可以大大加快畫圓的速度!
跟光柵化方法一樣,我們還是採用步進的方法來逐點描繪,但這里的決策參數計算方式跟Bresenham不大一樣,設決策參數為p,則:
P=x2+y2-r2
對於任一個點(x,y),可以根據p的符號來判斷點是在圓內還是圓外還是在圓上,這里不多說,假設我們在(xk,yk)處繪制了一個像素,下一步需要確定的是(xk+1,yk)還是(xk+1,yk-1)更接近於圓,在此代入這兩個點的中點來求出決策參數:
Pk=(xk+1)2+(yk-1/2)2-r2
如果Pk<0,則yk上的像素更接近於圓,否則就是yk-1更接近於圓
同理可以推出Pk+1=Pk+2(xk+1)+(yk+12-yk2)-(yk+1-yk)+1
給出一個示例,這個圓比用Bresenham畫出來的好看多了:
#include<glglut.h>
classscreenPt
{
private:
intx,y;
public:
screenPt(){x=y=0;}
voidsetCoords(GLintxCoordValue,GLintyCoordValue)
{
x=xCoordValue;
y=yCoordValue;
}
GLintgetx()const
{
returnx;
}
GLintgety()const
{
returny;
}
voidincrementx(){x++;}
voiddecrementy(){y--;}
};
voiddraw_pixel(intxCoord,intyCoord)
{
glBegin(GL_POINTS);
glVertex2i(xCoord,yCoord);
glEnd();
}
voidcircleMidpoint(GLintxc,GLintyc,GLintradius)
{
screenPtcircPt;
GLintp=1-radius;
circPt.setCoords(0,radius);
voidcirclePlotPoints(GLint,GLint,screenPt);
circlePlotPoints(xc,yc,circPt);
while(circPt.getx()<circPt.gety())
{
circPt.incrementx();
if(p<0)
p+=2*circPt.getx()+1;
else
{
circPt.decrementy();
p+=2*(circPt.getx()-circPt.gety())+1;
}
circlePlotPoints(xc,yc,circPt);
}
}
voidcirclePlotPoints(GLintxc,GLintyc,screenPtcircPt)//描繪八分圓各點
{
draw_pixel(xc+circPt.getx(),yc+circPt.gety());
draw_pixel(xc-circPt.getx(),yc+circPt.gety());
draw_pixel(xc+circPt.getx(),yc-circPt.gety());
draw_pixel(xc-circPt.getx(),yc-circPt.gety());
draw_pixel(xc+circPt.gety(),yc+circPt.getx());
draw_pixel(xc-circPt.gety(),yc+circPt.getx());
draw_pixel(xc+circPt.gety(),yc-circPt.getx());
draw_pixel(xc-circPt.gety(),yc-circPt.getx());
}
voiddisplay()
{
//screenPtPt;
glClear(GL_COLOR_BUFFER_BIT);
circleMidpoint(250,250,200);
glFlush();
}
voidmyinit()
{
glClearColor(0.8,1.0,1.0,1.0);
glColor3f(0.0,0.0,1.0);
glPointSize(1.0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0,500.0,0.0,500.0);
}
voidmain(intargc,char**argv)
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
glutInitWindowSize(500,500);
glutInitWindowPosition(200.0,200.0);
glutCreateWindow("CG_test_中點畫圓example");
glutDisplayFunc(display);
myinit();
glutMainLoop();
}
運行效果:
② 畫圓為什麼要用Bresenham演算法
演算法引入的本意是解決像素填充的問題的
點和線這種東西在理論上都是沒有寬度的,但是要在屏幕上繪制的時候就要去填充像素以形成痕跡
一行上經常有2個以上的像素都被線所貫穿, 如何填充是個問題
而且像素填充本身是使用非常頻繁的需求,故而畫線的演算法效率是非常重要的,對整個系統影響巨大
Bresenham演算法是通過增量計算的方式快速判別下一個行或者列上的要填充的像素的位置,從計算上來說非常的節省,幾乎都是整數的演算法,速度非常的快
③ 關於橢圓中點Bresenham演算法,請教高手,急用!分暫時不夠,夠了之後一定補上,謝謝各位了!
Bresenham演算法;
多邊形迫近法—圓與橢圓
...
推導出圓弧的增量演算法的表達式:
缺點:所產生的圓是不封閉的,且該圓的半徑有不斷增大的趨勢。
④ bresenham演算法的演算法
void IntegerBresenhamlin(int x0,int y0,int x1,int y1,int color)
{
int x,y,dx,dy,unitx,unity,fabs_dx,fabs_dy,e;
unsigned char i;
dx=x1-x0;
dy=y1-y0;
fabs_dx = (int)fabs(dx);
fabs_dy = (int)fabs(dy);
unitx = dx / fabs_dx ;
unity = dy / fabs_dy ;
x=x0;
y=y0;
if( fabs_dx> fabs_dy )
{
e=-fabs_dx;
for(i=0;i<=fabs_dx;i++)
{
drawpixel(x,y,color);
x+=unitx,e=e+2*fabs_dy;
if(e>=0)
{
y+=unity;e=e-2*fabs_dx;
}
} // for end
}
else
{
e-=fabs_dy;
for(i=0;i<=fabs_dy;i++)
{
drawpixel(x,y,color);
y+=unity,e=e+2*fabs_dx;
if(e>=0)
{
x+=unitx;e=e-2*fabs_dy;
}
} // for end
}// if end
} //:~
⑤ 會用C語言畫圖的(圓)Bresenham演算法的高手幫忙看下!
//包含頭文件這個不用我說了吧
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
#include<graphics.h>
//交換a,b的值函數
void Swap(int *a,int *b);
//Bresenhen畫園函數,圓心坐標(centerx,centery)半徑radius線條顏色color
void BresenhemCircle(int centerx, int centery, int radius, int color, int type);
void initgr(void) /* BGI初始化 */
{
int gd = DETECT, gm = 0; /* 和gd = VGA,gm = VGAHI是同樣效果 */
registerbgidriver(EGAVGA_driver);/* 注冊BGI驅動後可以不需要.BGI文件的支持運行 */
initgraph(&gd, &gm, "");//初始化圖形,必須寫的
setbkcolor(WHITE);//設置背景顏色
}
int main(void)
{
int centerx,centery,radius,color,type;//變數定義總該知道的吧
printf("centerx,centery\n");//輸出提示信息,這個總該知道的吧
scanf("%d",¢erx);//輸入中心坐標橫坐標
scanf("%d",¢ery);//
printf("radius\n");
scanf("%d",&radius);
printf("color,type\n");
scanf("%d",&color);
scanf("%d",&type);
initgr(); /*BGI初始化 */
BresenhemCircle(centerx,centery,radius,color,type);//重點理解這個函數
/*setcolor(RED);
circle(centerx, centery,radius);*/
/*Swap(&xs,&xe);
printf("%d,%d",xs,xe); */
getch();
closegraph();
}
void BresenhemCircle(int centerx, int centery, int radius, int color, int type)
{
int x =type= 0;//這些賦值語句應該能夠看懂的吧
int y = radius;
int delta = 2*(1-radius);
int direction;
while (y >= 0) {//循環,如果y>=0就繼續執行{}裡面的語句
if (!type) { //!type表示如果type=0就執行{}裡面的語句
putpixel(centerx+x, centery+y, color);
//前面兩個參數是坐標,後面一個是顏色值,在(centerx+x, centery+y)畫一個點
putpixel(centerx-x, centery+y, color);
putpixel(centerx-x, centery-y, color);
putpixel(centerx+x, centery-y, color);
}
else {//如果type=1就執行下面的
line(centerx+x, centery+y, centerx+x, centery-y);
line(centerx-x, centery+y, centerx-x, centery-y);
}
if (delta < 0) {//這個類似上面的,只不過這個嵌套了一層if-else if-else
if ((2*(delta+y)-1) < 0) {
direction = 1;
}
else {
direction = 2;
}
}
else if(delta > 0) {
if ((2*(delta-x)-1) <= 0) {
direction = 2;
}
else {
direction = 3;
}
}
else {
direction=2;
}
switch(direction) {//選擇如果direction=1執行case 1:到case 2:直接的語句,如果沒有break那麼case 2:下面的語句也會被執行
case 1:
x++;
delta += (2*x+1);
break;
case 2:
x++;
y--;
delta += 2*(x-y+1);
break;
case 3:
y--;
delta += (-2*y+1);
break;
}
}
}
⑥ C語言用Bresenham演算法畫圓,哪位高手教教,主要是演算法里的內容,謝謝!
的確哈,關鍵在於對delta的理解
可以看到,都是delta=2*(1-radius)這樣的,起作用應該是判斷要畫的點x、y坐標的變化趨勢,先把我注釋了的代碼貼下,加了getch();可以看到畫的過程
-----------------------------------------------------------------
#include<graphics.h>
#include<stdio.h>
void BresenhemCircle(int centerx, int centery, int radius, int color, int type);
void main()
{
int drive=DETECT,mode;
int i,j;
initgraph(&drive,&mode,"");
BresenhemCircle(300,200,100,15,0);
getch();
}
void BresenhemCircle(int centerx, int centery, int radius, int color, int type)
{
int x =type = 0;/*初始橫坐標為原點*/
int y = radius; /*初始縱坐標遠離原點*/
int delta = 2*(1-radius);
int direction;
while (y >= 0)
{
getch();
if (!type)/*執行*/
{
/*在上半圓畫兩點*/
putpixel(centerx+x, centery+y, color);
putpixel(centerx-x, centery+y, color);
/*在下半圓畫兩點*/
putpixel(centerx-x, centery-y, color);
putpixel(centerx+x, centery-y, color);
getch();
}
else/*不執行*/
{
line(centerx+x, centery+y, centerx+x, centery-y);
line(centerx-x, centery+y, centerx-x, centery-y);
getch();
}
/*以下代碼設置下次四點的位置,圓是對稱的,且此方法相當於同時畫四個圓弧
觀察右上方圓弧可知,前一半是x增的要快些,後一半是y減的快些*/
if (delta < 0)
{
if ((2*(delta+y)-1) < 0)
direction = 1; /*選擇橫向加*/
else
direction = 2;
}
else if(delta > 0)
{
if ((2*(delta-x)-1) > 0)
direction = 3; /*選擇縱向減*/
else
direction = 2;
}
else
direction=2;
switch(direction)
{
case 1:
x++;/*只橫坐標遠離原點*/
delta += (2*x+1); /*小執行到這,所以加*/
break;
case 2:
x++;
y--;/*橫向遠離,同時縱向靠近*/
delta += 2*(x-y+1); /*即(2*x+1)+(-2*y+1)*/
break;
case 3:
y--;/*只縱坐標靠近原點*/
delta += (-2*y+1); /*大執行到這,所以減*/
break;
}
}
}
⑦ 求大神解答 圓弧的Bresenham點生成演算法,通常把圓分成__________個部分
圓弧的
Bresenham
點生成演算法,
通常把圓分成
ˍ
8
ˍ
個部分,
如果
f
i
=(x
i
+1)
2
+y
i
2
-R
2
,
g
i
=(x
i
+1)
2
+(y
i
-1)
2
-R
2
,
e=
∣
f
i
∣
-
∣
g
i
∣,當點(
X
i
,
Y
i
)的
e
i
≥
0
則下一點為
D
,其坐標為(
X
i
+1
,
ˍ
yi-1
ˍ
),
若
e
i
<
0
則
下一點為
H
,其坐標為
(X
i
+1
,
ˍ
yi
ˍ
)
。
⑧ c語言問題
一、 演算法設計及流程
1. 點
不管什麼樣的圖形歸根結底到屏幕,都是由一些顏色不一的象素點組成,為提高圖形的顯示效率,沒有用到系統的畫點函數,而採用了640*480*16模式下的直接寫屏技術畫點,該模式下的直接寫屏比320*200*256的直接寫屏要復雜的多,後者的視頻緩沖區是線性編址的,一個位元組對應屏幕上一點的顏色,而前者的視頻緩沖區被分成四個位面,屏幕上一點的顏色由每個位面上的一位組成的四位二進制數決定,由於四位二進制數的最大表示範圍是16,所以在這種模式下最多可同時顯示16種顏色。
在對視頻緩沖區的讀寫時,是一個位元組一個位元組寫的,只需要其中某一位時,就要用到位掩碼屏蔽掉其他的位,位掩碼就在圖形控制寄存器的位屏蔽寄存器里設置。先通過向埠號為0x3ce的索引寄存器寫入位屏蔽寄存器的索引號8,然後向埠號為0x3cf的寄存器寫入位掩碼值。設置好位掩碼後,直接向視頻緩沖區相應位置寫入顏色即為畫點函數。
取屏幕上一點顏色其實也就是畫點的反操作,畫點是將一個四位的二進制顏色值分配到四個位面,而取一點的顏色是將四個位面的顏色組合成一個四位二進制數。
2. 線
線其實就是由點組成的,通過連續的改變點的坐標,也就可以得到一條線。所以畫線的函數歸根結底也就是如何改變畫點的坐標。
畫線通常有DDA演算法,BRESENHAM演算法,這里採用的是BRESENHAM演算法。這種演算法從根本上講,是通過橫線與豎線的倍數關系來實現的。每次循環畫點後x、y中位移大的坐標變化一個單位,而當循環次數是兩者倍數關系時,x、y中位移小的坐標變化一個單位。為了使畫線函數能在八個方向都能畫,將增量為負的都轉化正的增量。
畫圖程序經常要用到moveto、lineto等函數,用於把點移動到某點或從當前點畫線到某點,為了模擬這些函數,設置了SX,SY兩個全局變數用來作為Moveto()的目的地和Drawlineto()的起始坐標。
3. 矩形及填充矩形
矩形是通過兩點確定的對角線來畫的,直接連上各點的坐標就可以了。填充矩形是通過一條線一條線畫的。這種演算法速度比較慢,較好的方法是用Fillscreen()裡面用到的方法,那是一個位元組一個位元組處理的。就因為畫矩形並不一定是整位元組開始整位元組結束的,開始處和結尾處就有了問題。我也把它們單獨拿出來處理,但還是沒做好,等有時間了再改吧。
4. 圓及弧
畫圓採用的是參數方程的方法。為了提高速度,角度的sin、cos值建立了一個表,要用時直接查表。這是因為在用BRESENHAM演算法畫橢圓時,效果不是很好,畫的橢圓不但厚薄不一,而且不閉合。估計是程序哪裡出問題了,乾脆都用參數方程的方法,又簡單,又省事。我這人通常是比較懶的。
弧主要是用來畫圓角矩形的,且只能畫圓弧。這也是用參數方程來畫的,跟畫圓不同的只是有了角度的限制。
5. 貝塞爾曲線
貝塞爾曲線其實主要也就是一個公式,跟參數方程畫圓是一回事,只是要傳入的參數要多一些。在用滑鼠控制時,因為有四個點,而用滑鼠對多點的採集有點不好做,於是先就初始化了一個四點的數組,用不按鍵、按左鍵、按右鍵分別控制三個點,左右鍵同時按時,確定下一條曲線。
其實用滑鼠畫貝塞爾曲線因該把一次、二次、三次的處理函數都寫出來,在按下左鍵時,標記下這點,再一次按下左鍵時,用畫一次貝塞爾曲線的函數畫,按下第三次時,用畫二次曲線的函數畫,按下第四次時才用畫三次曲線的函數畫。這樣就不用為每個點分配一個滑鼠按鍵了。
6. 填充
填充也是採用的種子填充法,不過不是直接從種子開始填色,而是先從種子出發,找到種子沿x最小的邊界,然後填上一點,判斷這一點的上邊一點和下邊一點,如果不為邊界並且未被填色,則壓入棧中,然後x增1後判斷是否到達這一行x的最大值(既邊界),如不是,則循環處理這一行,直到到達邊界,再彈出一個點繼續循環處理。由於是一個點一個點處理,所以速度比較慢。
為了對一個圖形的不同顏色邊界也能填充,填色時沒有傳入圖形的邊界顏色,而是採用先取出種子的顏色,在填充下一個點時,把下一點的顏色和種子顏色比較,如果相同則填色,不同則作為邊界。
7. 漢字及字元
圖形模式下顯示漢字其實是一件比較麻煩的事,一般要用到漢字字型檔,生成的可執行文件也得在有字型檔的環境下運行。我這里採用了漢字無字型檔技術,生成的文件不依賴任何其他文件。
無字型檔技術是通過從字型檔文件提取需要的中文點陣字模建立一個類似字型檔的字型檔數組。它可以大大提高漢字的顯示速度。在建立字型檔數組時,將字模數組進行了排序,所以在顯示漢字時
文章來自: 好喜愛學習網(http://www.haoxiai.net) 網址:http://www.haoxiai.net/bianchengyuyan/cyuyan/11968.html
⑨ 用C實現Bresenham演算法生成直線和圓的程序(要求具體步驟有必要解述)
Bresenham演算法生成直線
假定直線從(x1,y1)到(x2,y2),
令dx=x2-x1,dy=y2-y1
不妨設(dx,dy)在第一象限,並且直線的斜率不大於1
畫線過程中有三個循環變數
x,y,d
初值
x=x1,y=y1,d=2*dy-dx
循環,直到x==x2為止
{
如果d>=0,y++,d+=2*(dy-dx)
如果d<0 ,x++,d+=2*dy
}
如果(dx,dy)不在第一象限,要做變換,即先把第一象限的畫出來
如果斜率大於1,x,y交換
非常簡單的,很容易實現
圓的演算法:
int Bres(int x0,int y0,double r,int color)
{
int x,y,d;
x=0;
y=(int)r;
d=(int)(3-2*r);
while(x<y)
{
cirpot(x0,y0,x,y,color);
if(d<0)
d+=4*x+6;
else
{
d+=4*(x-y)+10;
y--;
}
x++;
}
if(x==y)
cirpot(x0,y0,x,y,color);
return(0);
}
int cirpot(int x0,int y0,int x,int y,int color)
{
setcolor(color);
putxicl((x0+x),(y0+y));
putxicl((x0+y),(y0+x));
putxicl((x0+y),(y0-x));
putxicl((x0+x),(y0-y));
putxicl((x0-x),(y0-y));
putxicl((x0-y),(y0-x));
putxicl((x0-y),(y0+x));
putxicl((x0-x),(y0+y));
setcolor(color);
return(0);
}
這是圓的演算法,你若要整個程序,把你的電郵給我,我給你發過去、
運行環境是Turboc 2.0
int Bresline(int x1,inty1,int x2,int y2,int color)
{
int color,itag;
int dx,dy,tx,ty,inc1,inc2,d,curx,cury;
setcolor(color);
putxicl(x1,y1);
if(x1==x2&&y1==y2)
{
setcolor(color);
return(1);
}
itag=0;
dx=abs(x2-x1);
dy=abs(y2-y1);
if(dx<dy)
{
itag=1;]
iswap(&x1,&y1);
iswap(&x2,&y2);
iswap(&dx,&dy);
}
tx=(x2-x1)>0? 1:-1;
ty=(y2-y1)>0? 1:-1;
curx=x1;
cury=y1;
inc1=2*dy;
inc2=2*(dy-dx);
d=inc1-dx;
while(curx!x2)
{
if(d<0)
{
d+=inc1;
}
else
{
cury+=ty;
d+=inc2;
}
if(itag)
setpixel(cury,curx);
else
setpixel(curx,cury);
curxd+=tx;
}
setcolor(color);
return(0);
}
iswap(int*a,int*b)
{
int tmp;
tmp=*a;
*a=*b;
*b=tmp;
}
這是直線的演算法:和圓的差不多,你可以參考一下:)
⑩ 橢圓成生演算法
只寫步驟,不寫代碼了。
和樓主共通過,樓主也是這方面的專家,因此步驟就不寫太詳細了,只寫幾個關鍵點吧。
方法1:(最通常)
通過 sin 和 cos 乘兩軸長在原點畫出正向橢圓,然後傾斜、偏移即可。
這樣需要考慮弧度的間隔,否則兩點之間並不連續。而盲目的細分弧度,會加重運算負擔。
在許多 CAD 軟體中,是通過設置圓的內接 n 邊形來代表圓的,就是用線段連接。
將 n 邊型的取值增大,橢圓就會很平滑了。
問題還有,就是長軸端的弧度,點會分布的比較稀少,因為屏幕解析度並不是很高,所以可以用 長軸/短軸 的比值,來非等步長的增加弧度取值。
方法2:(近似求解)
通過4條貝塞爾曲線,可以連接成一個近似的橢圓。每段貝塞爾曲線代表原軸向橢圓的1/2*PI弧度,這樣做最大誤差只有0.027%。
每條貝塞爾曲線的四個控制點可以通過橢圓的外接矩形運算得出。
以掃描線方法的實現:
與樓主溝通過程中,提到了以掃描線的形式實現橢圓繪制過程。
常規方法:
縱向一個像素的移動掃描線,計算其與橢圓的兩個交點,並與上一條掃描線的兩個交點通過直線連接。第一次和最後一次與橢圓相交需要連接兩個交點。
這種方法比較麻煩。
採用緩沖區的解決辦法:
許多游戲都使用繪圖緩沖區,不過這里用來實現掃描線繪制。
在內存中創建一個 DC 設備,將所有的繪圖都轉移到該 DC 設備上,然後通過 DC 設備和屏幕設備之間簡單的行復制就可以了。
這樣應該就完美的解決了樓主的問題。