1.DDA算法
我们在画直线时我们取的像素都在确定的两个像素里选择。
DDA直线算法在于利用K或者K的倒数,我们都知道k=dy/dx,所以是单位x内y的变化。
不过在屏幕内我们通常以像素为单位,所以当|k|<1时我们以dx=1,dy=k。当|k|>=1,我们发现y比x走的多,|dy/dx|>1即dy>dx,所以为了在机器中我们以y走一个像素,x增加1/k。
优点:比较易于实现,贴近数学
缺点:有浮点数的处理(k的取整,浮点数的加法),效率不高
代码如下:
// DDA直线算法
function DDALine(x0,y0,x1,y1,color) {
// 定义初始化参数
var dx,dy,k,y;
y=y0;
x=x0;
dx=0.0+x1-x0;
dy=0.0+y1-y0;
k=dy/dx;
kReciprocal=dx/dy;
// 根据点的位置关系(判断大小)、以及斜率将初始点设置好
if (Math.abs(k)<1) {
var xMax=x0>x1?x0:x1;
var xMin=x0<x1?x0:x1;
var yMax=xMin!=x0?y0:y1;
var yMin=xMin==x0?y0:y1;
// 根据增量k来画点
for (var xn=xMin; xn<=xMax;) {
drawPixel(xn,Math.floor(yMin+0.5),aposLocation,context);
xn++;
yMin+=k;
}
}else {
var yMax=y0>y1?y0:y1;
var yMin=y0<y1?y0:y1;
var xMax=yMin!=y0?x0:x1;
var xMin=yMin==y0?x0:x1;
for (var yn=yMin; yn<=yMax;) {
drawPixel(Math.floor(xMin+0.5),yn,aposLocation,context);
yn++;
xMin+=kReciprocal;
}
}
}
2.中点画线算法
中点画线就是以中点到直线的距离判断取点的位置,若中点带入直线,判断符号就能决策取哪个点。但是我们的k取不同值时,我们的判别式以及判别式增量需要变化。
优点:进一步减少了浮点数的运算
代码如下:
// 中点直线画线
function MidPointLine(x0,y0,x1,y1,color) {
var dx,dy,k,y,x;
var a,b,d1,d2,d;
dx=0.0+x1-x0;
dy=0.0+y1-y0;
k=dy/dx;
kReciprocal=dx/dy;
y=y0;x=x0;
// 根据k的值来设置起始点
if (Math.abs(k)<1) {
var xMax=x0>x1?x0:x1;
var xMin=x0<x1?x0:x1;
var yMax=xMin!=x0?y0:y1;
var yMin=xMin==x0?y0:y1;
}else {
var yMax=y0>y1?y0:y1;
var yMin=y0<y1?y0:y1;
var xMax=yMin!=y0?x0:x1;
var xMin=yMin==y0?x0:x1;
}
x0=xMin;x1=xMax;y0=yMin;y1=yMax;y=y0;x=x0;
if (Math.abs(k)<1) {
a=y0-y1;
b=x1-x0;
b=k>0?b:-b;
d=2*a+b;
d1=k>0?2*a:2*(a+b);
d2=k>0?2*(a+b):2*a;
// 根据k的正负确定每次增加或减少
var uFactor=k>0?1:0;
var dFactor=k>0?0:-1;
drawPixel(x,y,aposLocation,context);
while (x<x1) {
if (d<0) {
x++;y+=uFactor;d+=d2;
}else {
x++;y+=dFactor;d+=d1;
}
drawPixel(x,y,aposLocation,context);
}
}else {
a=x0-x1;
b=y1-y0;
b=k>0?b:-b;
d=2*a+b;
d1=k>0?2*a:2*(a+b);
d2=k>0?2*(a+b):2*a;
var dFactor=k>0?0:-1;
var uFactor=k>0?1:0;
drawPixel(x,y,aposLocation,context);
while (y<y1) {
if (d<0) {
x+=uFactor;y++;d+=d2;
}else {
y++;x+=dFactor;d+=d1;
}
drawPixel(x,y,aposLocation,context);
}
}
}
3.Bresenham画线算法
这里是提前引入一个初值,然后后边不断累加一个增量来判断符号来判断点的位置。虽然引入0.5但是我们乘二就可以解决浮点数的问题,这个其实是DDA的变种,原理相似但是更为高级的是引入初始的判别值,经过变形去掉了浮点数,也只有一个增量。更易于机器的实现。
function BresenhamLine(x0,y0,x1,y1,color) {
var x,y,dx,dy,c,dy_2,dx_2,e,k,kReciprocal;
k=(y1-y0)/(x1-x0);
if (Math.abs(k)<1) {
var xMax=x0>x1?x0:x1;
var xMin=x0<x1?x0:x1;
var yMax=xMin!=x0?y0:y1;
var yMin=xMin==x0?y0:y1;
}else {
var yMax=y0>y1?y0:y1;
var yMin=y0<y1?y0:y1;
var xMax=yMin!=y0?x0:x1;
var xMin=yMin==y0?x0:x1;
}
x0=xMin;x1=xMax;y0=yMin;y1=yMax;y=y0;x=x0;
dx=x1-x0;dy=y1-y0;e=-dx;
x=x0;y=y0;
dy_2=2*dy;
dx_2=2*dx;
if (Math.abs(k)<1) {
if (k>0) {
for (var i = 0; i <=dx; i++) {
drawPixel(x,y,aposLocation,context);
x++;e=e+dy_2;
if (e>=0) {
y++;e=e-dx_2;
}
}
}else{
e=-e;
for (var i = 0; i <=dx; i++) {
drawPixel(x,y,aposLocation,context);
x++;e=e+dy_2;
if (e<=0) {
y--;e=e+dx_2;
}
}
}
}else{
if (k>0) {
for (var i = 0; i <=dy; i++) {
drawPixel(x,y,aposLocation,context);
y++;e=e+dx_2;
if (e>=0) {
x++;e=e-dy_2;
}
}
}else {
e=-e;
for (var i = 0; i <=dy; i++) {
drawPixel(x,y,aposLocation,context);
y++;e=e+dx_2;
if (e<=0) {
x--;e=e+dy_2;
}
}
}
}
}