直线段的矢栅转换算法(DDA算法、中心画线算法、Bresenham算法)
生活随笔
收集整理的這篇文章主要介紹了
直线段的矢栅转换算法(DDA算法、中心画线算法、Bresenham算法)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
直線段的矢柵轉換算法(DDA算法、中心畫線算法、Bresenham算法)
以下為drawLine.cpp,分別對相應的原理進行了注釋,只需調用相應的函數即可實現。
#include "drawLine.h" #include "setPixel.h" #include "cmath"void DDALine(int x0, int y0, int x1, int y1) { //DDA算法實現畫直線float x=x0,y=y0;float dx=x1-x0;float dy=y1-y0;float xadd,yadd; //定義x,y方向增量int step; //定義總的步數if(abs(dx)>abs(dy)){ //dx絕對值大于dy,則表明線斜率在1a,2a,3a,4a區域,此時x增加1或-1,y增加k或-k.step=abs(dx); //此時步數為x方向長度float yadd=(float)dy/(float)step;float xadd=(x1 - x0) > 0 ? 1 : -1; //分別用dx,dy除步數得到x,y方向增量值for(int i=0;i<=step;i++){ //利用總步數建立循環setPixel(x,int(y+0.5)); //填充點y=y+yadd; x=x+xadd; //x,y方向分別進行增加相應的分量}}else{ //dy絕對值大于dx,斜率在1b,2b,3b,4b區間,此時交換x,y,并將步數用|dy|代替.step=abs(dy);yadd=(y1 - y0) > 0 ? 1 : -1;xadd=(float)dx/(float)step;for(int i=0;i<=step;++i){setPixel(int(x+0.5),int(y));y=y+yadd;x=x+xadd;}} }void swap_value(int &a,int &b){ //交換兩個參數數值的函數int temp=a; //temp為中間參數a=b;b=temp; }void midpoint_line(int x0,int y0,int x1,int y1){int a, b, d2, x, y, flag = 0;if (abs(x1 - x0) < abs(y1 - y0)) //如果|k|>1,則將兩個點進行交換,并讓flag為1.{swap_value(x0,y0);swap_value(x1,y1); flag = 1; //判斷|k|值與1的關系,0到1時為0,>1時為1.}if (x0 > x1) { //保證x0<x1,則可以把畫3,4區域線合并到1,2區域中。swap_value(x0, x1);swap_value(y0, y1);}a = y0 - y1;b = x1 - x0;d2 = 2*a + b; //擺脫小數點,提高效率,d0=2a+bif (y0 < y1) { //k>0時,即畫1a和3a區域,同時畫出交換x,y過后在1a,3a區域的1b,3b區域.x = x0; y = y0;setPixel(x,y); //繪制點,先繪制x0,y0.while (x < x1) //直到繪制到x1終點截至,利用while循環繪制.{if(d2 < 0) //di小于0時,y增加,di增加2a+2b{x++;y++;d2 =d2+ 2*a + 2*b;}else { //di大于0時,y不變,di增加2ax++;d2 =d2+ 2 * a;}if(flag) //|k|>1,此時x,y已交換,繪制時需要交換x,y.setPixel(y, x);elsesetPixel(x, y); //0=<|k|<1,此時直接繪制相應點.} }else { //k<0,此時繪制4a和2a區域,同時畫出交換x,y過后在2a,4a區域的2b,4b區域.x = x1;y = y1;setPixel(x, y);while (x >x0){if (d2 < 0){x--;y++;d2 = d2-2 * a + 2 * b;}else {x--;d2 =d2- 2 * a;}if (flag) //|k|>1,交換x,y,繪制setPixel(y, x);elsesetPixel(x, y);}} }void Bresenham_line1(int x0,int y0,int x1,int y1){ //方法一,代碼較長int dx = x1 - x0; //x偏移量int dy = y1 - y0; //y偏移量int ux = dx >0 ? 1 : -1; //x伸展方向int uy = dy >0 ? 1 : -1; //y伸展方向int dx2 = abs(dx << 1); //x偏移量乘2int dy2 = abs(dy << 1); //y偏移量乘2if (abs(dx)>abs(dy)) //以x為增量方向計算{int e = -dx; //e = -0.5 * 2 * dx,把e 用2 * dx* e替換int x = x0;//起點x坐標int y = y0;//起點y坐標while (x!=x1+ux){setPixel(x,y);e = e + dy2; //來自 2*e*dx= 2*e*dx + 2dy if (e > 0) //e是整數且大于0時表示要取右上的點(否則是右下的點) {if (y!=y1){y += uy;}e = e - dx2;//2*e*dx = 2*e*dx - 2*dx}x += ux;}}else{//以y為增量方向計算int e = -dy; //e = -0.5 * 2 * dy,把e 用2 * dy* e替換int x = x0;//起點x坐標int y = y0;//起點y坐標while (y!=y1+uy){setPixel(x,y);e = e + dx2;//來自 2*e*dy= 2*e*dy + 2dyif (e > 0)//e是整數且大于0時表示要取右上的點(否則是右下的點) { if (x!=x1){x += ux;}e = e - dy2;//2*e*dy = 2*e*dy - 2*dy}y += uy;}} }void Bresenham_line(int x0,int y0,int x1,int y1 ){ //方法二,較簡便setPixel(x0,y0);int dx, dy;int flag=0;dx = abs(x1-x0);dy = abs(y1-y0);if (dx == 0 && dy == 0) //如果就x0,y0一個點,則繪制結束.return;if (dy > dx) //如果|k|>1,則將x,y值進行交換,同時令flag=1,做好標記{flag = 1;swap_value(x0,y0);swap_value(x1,y1);swap_value(dx,dy);}int tx = (x1 - x0) > 0 ? 1 : -1; //判斷位置關系確定步長正負int ty = (y1 - y0) > 0 ? 1 : -1;int curx = x0 + 1;int cury = y0; //將第一個點作為初值賦予curx,cury變量int dS = 2 * dy;int dT = 2 * (dy-dx);int d =dS-dx;while (curx != x1) //利用x進行循環{if (d >= 0) { //根據d進行區分d += dT;cury += ty;}else{d += dS;}if (flag) //flag為1時,x,y需要進行交換.setPixel(cury,curx);elsesetPixel(curx, cury);curx+=tx;} }void draw_line(int x0, int y0, int x1, int y1) { //需要時調用相應的方法DDALine(x0,y0,x1,y1);//midpoint_line(x0,y0,x1,y1);//Bresenham_line(x0,y0,x1,y1);//Bresenham_line1(x0,y0,x1,y1); //舍棄 }總結
以上是生活随笔為你收集整理的直线段的矢栅转换算法(DDA算法、中心画线算法、Bresenham算法)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: golang 结构体断言_Golang中
- 下一篇: PHP上传文件到七牛云和阿里云