导航:首页 > 源码编译 > 改进的bresenham的算法

改进的bresenham的算法

发布时间:2022-11-03 05:39:03

❶ dda法生成直线的基本原理是什么为什么说Bersenham画圆的算法效率较高

DDA算法主要是根据直线公式y = kx + b来推导出来的,其关键之处在于如何设定单位步进,即一个方向的步进为单位步进,另一个方向的步进必然是小于1。算法的具体思路如下:
1. 输入直线的起点、终点;
2. 计算x方向的间距:△X和y方向的间距:△Y。
3. 确定单位步进,取MaxSteps = max(△X,△Y); 若△X>=△Y,则X方向的步进为单位步进,X方向步进一个单位,Y方向步进△Y/MaxSteps;否则相反。
4. 设置第一个点的像素值
5. 令循环初始值为1,循环次数为MaxSteps,定义变量x,y,执行以下计算:
a. x增加一个单位步进,y增加一个单位步进
b. 设置位置为(x,y)的像素值

Bresenham算法是DDA算法画线算法的一种改进算法。本质上它也是采取了步进的思想。不过它比DDA算法作了优化,避免了步进时浮点数运算,同时为选取符合直线方程的点提供了一个好思路。首先通过直线的斜率确定了在x方向进行单位步进还是y方向进行单位步进:当斜率k的绝对值|k|<1时,在x方向进行单位步进;当斜率k的绝对值|k|>1时,在y方向进行单位步进。
1. 输入线段的起点和终点。
2. 判断线段的斜率是否存在(即起点和终点的x坐标是否相同),若相同,即斜率不存在,
只需计算y方向的单位步进(△Y+1次),x方向的坐标保持不变即可绘制直线。
3. 计算线段的斜率k,分为下面几种情况处理
a. k等于0,即线段平行于x轴,即程序只需计算x方向的单位步进,y方向的值不变
b. |k|等于1,即线段的x方向的单位步进和y方向的单位步进一样,皆为1。直接循环△X次计算x和y坐标。
4. 根据输入的起点和终点的x、y坐标值的大小决定x方向和y方向的单位步进是1还是-1
6. 画出第一个点。
7. 若|k| <1,设m =0,计算P0,如果Pm>0,下一个要绘制的点为(Xm+单位步进,Ym),
Pm+1 = Pm -2*△Y;
否则要绘制的点为(Xm+单位步进,Ym+单位步进)
Pm+1 = Pm+2*△X-2*△Y;
8. 重复执行第七步△X-1次;
9. 若|k| <1,设m =0,计算Q0,如果Qm>0,下一个要绘制的点为(Xm,Ym+单位步进),
Pm+1 = Pm -2*△X;
否则要绘制的点为(Xm+单位步进,Ym+单位步进)
Pm+1 = Pm+2*△Y-2*△X;
10. 重复执行第9步△Y-1次;

❷ 计算机图形学直线生成算法

我连画圆的一块给你吧
需要橡皮筋
椭圆
树什么的可以和我说
我是用
c#写的
using
System;
using
System.Collections.Generic;
using
System.ComponentModel;
using
System.Data;
using
System.Drawing;
using
System.Text;
using
System.Windows.Forms;
namespace
line
{
public
partial
class
Form1
:
Form
{
Graphics
g;
public
Form1()
{
InitializeComponent();
g
=
pictureBox1.CreateGraphics();
}
private
void
button1_Click_1(object
sender,
EventArgs
e)
{
//
g.TranslateTransform(-300,-300);
g.Clear(BackColor);
double
x1,
x2,
y1,
y2;
double
x,
y;
x1
=
System.Convert.ToSingle(textBox1.Text);
y1
=
System.Convert.ToSingle(textBox2.Text);
x2
=
System.Convert.ToSingle(textBox3.Text);
y2
=
System.Convert.ToSingle(textBox4.Text);
x
=
x1;
double
k
=
(y1
-
y2)
/
(x1
-
x2);
Color
color1
=
Color.FromArgb(255,
0,
0);
//定义颜色
Brush
bru1
=
new
SolidBrush(color1);//定义笔
Color
color2
=
Color.FromArgb(0,
255,
0);
//定义颜色
Brush
bru2
=
new
SolidBrush(color2);//定义笔
Pen
pen1
=
new
Pen(bru1,
1);
Pen
pen2
=
new
Pen(bru2,
1);
while
(x
<
x2)
{
//
textBox3.Text
=
System.Convert.ToString(k);
y
=
(double)k
*
(x
-
x1)
+
y1;
double
a;
a=y%1;
float
xx
=
Convert.ToSingle(x);
float
yy
=
Convert.ToSingle(y);
if
(a
>
0.5)
{
g.DrawLine(pen1,
xx,
yy,
xx,yy+1);
}
else
{
g.DrawLine(pen2,
xx,
yy,
xx,
yy+1);
}
x++;
}
//g.DrawLine(p,10,10,100,100);
}
private
void
button2_Click(object
sender,
EventArgs
e)
{
g.TranslateTransform(300,
300);
g.Clear(BackColor);
float
r;//r为圆的圆心
r
=System.Convert.ToSingle(textBox6.Text);
Color
color1
=
Color.FromArgb(255,
0,
0);
//定义颜色
Brush
bru1
=
new
SolidBrush(color1);//定义笔
Color
color2
=
Color.FromArgb(0,
255,
0);
//定义颜色
Brush
bru2
=
new
SolidBrush(color2);//定义笔
Pen
pen1
=
new
Pen(bru1,1);
Pen
pen2
=
new
Pen(bru2,
1);
float
x
=
0;
float
y
=
r;
while
(x
<r+3)
{
y
=
(float)System.Math.Sqrt(r
*
r
-
x
*
x);
float
a;
a
=
y
%
1;
y
=
y
-
a;
if
(a
>
0.5)
{
g.DrawLine(pen1,
x,
y,
x,
y+1);
g.DrawLine(pen1,
-x,
y,
-x,
y
+
1);
g.DrawLine(pen1,
x,
-y,
x,
-y
+
1);
g.DrawLine(pen1,
-x,
-y,
-x,
-y
+
1);
}
else
{
g.DrawLine(pen2,
x,
y,
x,
y+1);
g.DrawLine(pen2,
-x,
y,
-x,
y
+
1);
g.DrawLine(pen2,
x,-
y,
x,-
y
+
1);
g.DrawLine(pen2,
-x,
-y,-
x,
-y
+
1);
}
x++;
}
g.TranslateTransform(-300,
-300);
}
private
void
button3_Click(object
sender,
EventArgs
e)
{
}
private
void
comboBox1_SelectedIndexChanged(object
sender,
EventArgs
e)
{
switch
(comboBox1.Text)
{
case
"画圆":
{
textBox1.Visible
=
false;
textBox2.Visible
=
false;
textBox3.Visible
=
false;
textBox4.Visible
=
false;
textBox5.Visible
=
true;
textBox6.Visible
=
true;
textBox7.Visible
=
false;
textBox8.Visible
=
false;
label1.Visible
=
false;
label2.Visible
=
false;
label3.Visible
=
false;
label4.Visible
=
false;
label5.Visible
=
true;
label6.Visible
=
true;
label7.Visible
=
false;
label8.Visible
=
false;
label9.Visible
=
true;
button1.Visible
=
false;
button2.Visible
=
true;
button3.Visible
=
false;
break;
}
case"画线":
{
textBox1.Visible
=
true;
textBox2.Visible
=
true;
textBox3.Visible
=
true;
textBox4.Visible
=
true;
textBox5.Visible
=
false;
textBox6.Visible
=
false;
textBox7.Visible
=
false;
textBox8.Visible
=
false;
label1.Visible
=
true;
label2.Visible
=
true;
label3.Visible
=
true;
label4.Visible
=
true;
label5.Visible
=
false;
label6.Visible
=
false;
label7.Visible
=
false;
label8.Visible
=
false;
label9.Visible
=
false;
button1.Visible
=
true;
button2.Visible
=
false;
button3.Visible
=
false;
break;
}
case"画椭圆":
{
textBox1.Visible
=
false;
textBox2.Visible
=
false;
textBox3.Visible
=
false;
textBox4.Visible
=
false;
textBox5.Visible
=
false;
textBox6.Visible
=
false;
textBox7.Visible
=
true;
textBox8.Visible
=
true;
label1.Visible
=
false;
label2.Visible
=
false;
label3.Visible
=
false;
label4.Visible
=
false;
label5.Visible
=
false;
label6.Visible
=
false;
label7.Visible
=
true;
label8.Visible
=
true;
label9.Visible
=
false;
button1.Visible
=
false;
button2.Visible
=
false;
button3.Visible
=
true;
break;
}
}
}
}
}

❸ 关于Bresenham算法的求助

今天一下子遇到三个类似的问题,所以我这篇东西就连续复制粘贴了三遍:

(下面的坐标本来是有下标的,但复制过来就变没了,你可能看的有点晕)

Bresenham算法是Bresenham提出的一种光栅线生成算法!

DDA算法表面上看起来很有效,并且代码也比较容易实现,但是显示每个像素都需要进行一次浮点数加法运算,而Bresenham算法的最大优点是不需要进行浮点数运算!这是一种精确而有效的光栅线生成算法,该算法仅使用增量整数计算,计算速度比DDA要快,另外,Bresenham算法还可用于显示圆和其他曲线,这里暂时只显示直线!

与DDA一样,我们假设线段的两个端点坐标是整数值(x0,y0)(xEnd,yEnd),且斜率m满足0<=m>=1!坐标轴的垂直轴表示扫描线位置,水平轴标识像素列,假设以单位x间隔取样,需要确定下一个每次取样时两个可能的像素位置中的哪一个更接近于线路径!

从给定线段的左端点(x0,y0)开始,逐步处理每个后继列(x位置),并在其扫描线y值最接近线段的像素处描出一点,假如已经确定要显示的像素在(xk,yk),那么下一步就要确定在列xk+1=xk+1上绘制哪个像素,是在位置(xk+1,yk)还是在(xk+1,yk+1)

在取样位置xk+1,我们使用dlower和pper来标识两个像素与数学上线路径的垂直偏移(就是通过这两个值来比较哪个点离线上的点最近,以下推导过程你可能看得有点晕,但都是为了推出后续的点而已,你可以结合下面例子程序中的Bresenham函数来看),在像素列xk+1处的直线上的y坐标根据直线方程可计算得:

y=m(xk+1)+b

那么可求得:

dlower=y-yk=m(xk+1)+b-yk

pper=(yk+1)-y=yk+1-m(xk+1)-b

令斜率m=dy/dx,引入决策参数Pk,定义为:

Pk=dx(dlower-pper)

=2dx*xk-2dy*yk+c

C是一个常数,值为2dx+dx(2b-1)

由此可以计算得到

pk+1=Pk+2dy-2dx(yk+1-yk)

其中yk+1-yk取0还是取1取决于参数Pk的符号,Pk为负时取0,Pk非负时取1!

而Pk为负时,下一个要绘制的点就是(xk+1,yk)且pk+1=Pk+2dy

Pk为非负时则下一个要绘制的点就是(xk+1,yk+1)且pk+1=Pk+2dy-2dx

至此,Bresenham算法介绍完毕,以下为某个示例:

#include<gl/glut.h>

#include<math.h>

#include<stdio.h>

voiddraw_pixel(intix,intiy)

{

glBegin(GL_POINTS);

glVertex2i(ix,iy);

glEnd();

}

voidBresenham(intx1,inty1,intxEnd,intyEnd)

{

intdx=abs(xEnd-x1),dy=abs(yEnd-y1);

intp=2*dy-dx;

inttwoDy=2*dy,twoDyMinusDx=2*dy-2*dx;

intx,y;

if(x1>xEnd)

{

x=xEnd;y=yEnd;

xEnd=x1;

}

else

{

x=x1;

y=y1;

}

draw_pixel(x,y);

while(x<xEnd)

{

x++;

if(p<0)

p+=twoDy;

else

{

y++;

p+=twoDyMinusDx;

draw_pixel(x,y);

}

}

}

voiddisplay()

{

glClear(GL_COLOR_BUFFER_BIT);

Bresenham(0,0,400,400);

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_Lineexample");

glutDisplayFunc(display);

myinit();

glutMainLoop();

}

运行效果:

❹ Bresenham直线算法的演算方法

Bresenham直线算法描绘的直线。假设我们需要由 (x0, y0) 这一点,绘画一直线至右下角的另一点(x1, y1),x,y分别代表其水平及垂直坐标,并且 x1 - x0 > y1 - y0。在此我们使用电脑系统常用的坐标系,即x坐标值沿x轴向右增长,y坐标值沿y轴向下增长。
因此x及y之值分别向右及向下增加,而两点之水平距离为x1 − x0且垂直距离为y1-y0。由此得之,该线的斜率必定介乎于1至0之间。而此算法之目的,就是找出在x0与x1之间,第x行相对应的第y列,从而得出一像素点,使得该像素点的位置最接近原本的线。
对于由(x0, y0)及(x1, y1)两点所组成之直线,公式如下:
因此,对于每一点的x,其y的值是
因为x及y皆为整数,但并非每一点x所对应的y皆为整数,故此没有必要去计算每一点x所对应之y值。反之由于此线之斜率介乎于1至0之间,故此我们只需要找出当x到达那一个数值时,会使y上升1,若x尚未到此值,则y不变。至于如何找出相关的x值,则需依靠斜率。斜率之计算方法为m = (y1 − y0) / (x1 − x0)。由于此值不变,故可于运算前预先计算,减少运算次数。
要实行此算法,我们需计算每一像素点与该线之间的误差。于上述例子中,误差应为每一点x中,其相对的像素点之y值与该线实际之y值的差距。每当x的值增加1,误差的值就会增加m。每当误差的值超出0.5,线就会比较靠近下一个映像点,因此y的值便会加1,且误差减1。
下列伪代码是这算法的简单表达(其中的plot(x,y)绘画该点,abs返回的是绝对值)。虽然用了代价较高的浮点运算,但很容易就可以改用整数运算(详见最佳化一节):
function line(x0, x1, y0, y1)
int deltax := x1 - x0
int deltay := y1 - y0
real error := 0
real deltaerr := deltay / deltax // 假设 deltax != 0 (非垂直线),
// 注意:需保留除法运算结果的小数部分
int y := y0
for x from x0 to x1
plot(x,y)
error := error + deltaerr
if abs(error) ≥ 0.5 then
y := y + 1
error := error - 1.0

❺ 写出直线段扫描转换的Bresenham算法,并生成从点P1(0,0)到点P2 (5,2)的直线段,要求写出每一步递推过程

没分?····不过既然我有现成的那就给你吧,不过复制粘贴而已!

Bresenham算法是Bresenham提出的一种光栅线生成算法!DDA算法表面上看起来很有效,并且代码也比较容易实现,但是显示每个像素都需要进行一次浮点数加法运算,而Bresenham算法的最大优点是不需要进行浮点数运算!这是一种精确而有效的光栅线生成算法,该算法仅使用增量整数计算,计算速度比DDA要快,另外,Bresenham算法还可用于显示圆和其他曲线,这里暂时只显示直线!

与DDA一样,我们假设线段的两个端点坐标是整数值(x0,y0)(xEnd,yEnd),且斜率m满足0<=m>=1!坐标轴的垂直轴表示扫描线位置,水平轴标识像素列,假设以单位x间隔取样,需要确定下一个每次取样时两个可能的像素位置中的哪一个更接近于线路径!

从给定线段的左端点(x0,y0)开始,逐步处理每个后继列(x位置),并在其扫描线y值最接近线段的像素处描出一点,假如已经确定要显示的像素在(xk,yk),那么下一步就要确定在列xk+1=xk+1上绘制哪个像素,是在位置(xk+1,yk)还是在(xk+1,yk+1)

在取样位置xk+1,我们使用dlower和pper来标识两个像素与数学上线路径的垂直偏移,在像素列xk+1处的直线上的y坐标根据直线方程可计算得:

y=m(xk+1)+b

那么可求得:

dlower=y-yk=m(xk+1)+b-yk

pper=(yk+1)-y=yk+1-m(xk+1)-b

令斜率m=dy/dx,引入决策参数Pk,定义为:

Pk=dx(dlower-pper)

=2dx*xk-2dy*yk+c

C是一个常数,值为2dx+dx(2b-1)

由此可以计算得到

pk+1=Pk+2dy-2dx(yk+1-yk)

其中yk+1-yk取0还是取1取决于参数Pk的符号,Pk为负时取0,Pk非负时取1!

而Pk为负时,下一个要绘制的点就是(xk+1,yk)且pk+1=Pk+2dy

Pk为非负时则下一个要绘制的点就是(xk+1,yk+1)且pk+1=Pk+2dy-2dx

至此,Bresenham算法介绍完毕,以下为某个示例:

#include<gl/glut.h>

#include<math.h>

#include<stdio.h>

voiddraw_pixel(intix,intiy)

{

glBegin(GL_POINTS);

glVertex2i(ix,iy);

glEnd();

}

voidBresenham(intx1,inty1,intxEnd,intyEnd)

{

intdx=abs(xEnd-x1),dy=abs(yEnd-y1);

intp=2*dy-dx;

inttwoDy=2*dy,twoDyMinusDx=2*dy-2*dx;

intx,y;

if(x1>xEnd)

{

x=xEnd;y=yEnd;

xEnd=x1;

}

else

{

x=x1;

y=y1;

}

draw_pixel(x,y);

while(x<xEnd)

{

x++;

if(p<0)

p+=twoDy;

else

{

y++;

p+=twoDyMinusDx;

draw_pixel(x,y);

}

}

}

voiddisplay()

{

glClear(GL_COLOR_BUFFER_BIT);

Bresenham(0,0,400,400);//这是我的线段两端点的坐标,你可以换成Bresenham(0,0,5,2),

//不过估计很短,看不清

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_Lineexample");

glutDisplayFunc(display);

myinit();

glutMainLoop();

}

程序运行效果如图:

❻ bresenham算法的原理

Bresenham算法是计算机图形学领域使用最广泛的直线扫描转换方法。
其原理是:
过各行、各列像素中心构造一组虚拟网格线,按直线从起点到终点的
顺序计算直线各垂直网格线的交点,然后确定该列像素中与此交点最近
的像素。
该算法的优点在于可以采用增量计算,使得对于每一列,只要检查一个误差项
的符号,就可以确定该列所求的像素。

❼ Bresenham画线算法

基本上Bresenham画线算法的思路如下:

// 假设该线段位于第一象限内且斜率大于0小于1,设起点为(x1,y1),终点为(x2,y2).
// 根据对称性,可推导至全象限内的线段.
1.画起点(x1,y1).
2.准备画下个点。x坐标增1,判断如果达到终点,则完成。否则,由图中可知,下个要画的点要么为当前点的右邻接点,要么是当前点的右上邻接点.
2.1.如果线段ax+by+c=0与x=x1+1的交点的y坐标大于M点的y坐标的话,下个点为U(x1+1,y1+1)
2.2.否则,下个点为B(x1+1,y1+1)
3.画点(U或者B).
4.跳回第2步.
5.结束.

这里需要细化的是怎么判断下个要画的点为当前点的右邻接点还是当前点的右上邻接点.

设线段方程:ax+by+c=0(x1<x<x2,y1<y<y2)
令dx=x2-x1,dy=y2-y1
则:斜率-a/b = dy/dx.

从第一个点开始,我们有F(x,1,y1) = a*x1+b*y1+c=0
下面求线段ax+by+c=0与x=x1+1的交点:
由a*(x1+1)+b*y+c = 0, 求出交点坐标y=(-c-a(x1+1))/b
所以交点与M的y坐标差值Sub1 = (-c-a(x1+1))/b - (y1+0.5) = -a/b-0.5,即Sub1的处始值为-a/b-0.5。

则可得条件当 Sub1 = -a/b-0.5>0时候,即下个点为U.
反之,下个点为B.
代入a/b,则Sub1 = dy/dx-0.5.

因为是个循环中都要判断Sub,所以得求出循环下的Sub表达式,我们可以求出Sub的差值的表达式.下面求x=x1+2时的Sub,即Sub2
1.如果下下个点是下个点的右上邻接点,则
Sub2 = (-c-a(x1+2))/b - (y1+1.5) = -2a/b - 1.5
故Sub差值Dsub = Sub2 - Sub1 = -2a/b - 1.5 - (-a/b-0.5) = -a/b - 1.代入a/b得Dsub = dy/dx -1;
2.如果下下个点是下个点的右邻接点,
Sub2 = (-c-a(x1+2))/b - (y1+0.5) = -2a/b - 0.5
故Sub差值Dsub = Sub2 - Sub1 = -2a/b - 0.5 - (-a/b-0.5) = -a/b. 代入a/b得Dsub = dy/dx;

于是,我们有了Sub的处始值Sub1 = -a/b-0.5 = dy/dx-0.5,又有了Sub的差值的表达式Dsub = dy/dx -1 (当Sub1 > 0)或 dy/dx(当Sub1 < 0).细化工作完成。

于是pcode可以细化如下:

// Pcode for Bresenham Line
// By SoRoMan
x=x1;
y=y1;
dx = x2-x1;
dy = y2-y1;
Sub = dy/dx-0.5; // 赋初值,下个要画的点与中点的差值

DrawPixel(x, y); // 画起点
while(x<x2)
{
x++;
if(Sub > 0) // 下个要画的点为当前点的右上邻接点
{
Sub += dy/dx - 1; //下下个要画的点与中点的差值
y++; // 右上邻接点y需增1
}
else// 下个要画的点为当前点的右邻接点
{
Sub += dy/dx;
}
// 画下个点
DrawPixel(x,y);
}

PS:一般优化:
为避免小数转整数以及除法运算,由于Sub只是用来进行正负判断,所以可以令Sub = 2*dx*Sub = 2dy-dx,则
相应的DSub = 2dy - 2dx或2dy.

思考1:如果Sub = 0时,会产生取两个点都可以的问题。这个问题还没深入。

❽ 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
} //:~

❾ bresenham算法的介绍

bresenham算法是计算机图形学中为了“显示器(屏幕或打印机)系由像素构成”的这个特性而设计出来的算法,使得在求直线各点的过程中全部以整数来运算,因而大幅度提升计算速度。

❿ 运动控制器2:GRBL的核心结构体block_t和BRESENHAM算法

typedef struct {

  第一部分:bresenham算法需要的入口条件,包括运动方向,X,Y,Z各需要运动多少步,以及完成这个BLOCK需要运动多少步。

  uint8_t  direction_bits;            //

  uint32_t steps_x, steps_y, steps_z; //

  int32_t  step_event_count;          //

Bresenham直线算法是用来描绘由两点所决定的直线的算法,它会算出一条线段在 n 维光栅上最接近的点。这个算法只会用到较为快速的整数加法、减法和位元移位,常用于绘制电脑画面中的直线。是计算机图形学中最先发展出来的算法。

GRBL中,圆弧是用直线段来接近描述的,所以不需要考虑,直接的画法通过下面的判断器,X先走。

把纵轴的一个方格的一半作为基准,如果在基准点以上,则Y轴走一步,如果在下面,则X继续走一步。而step_event_count为最终走的总步数,为X+Y总步数。

第二部分:

调度器用于计算加速度的内容,也就是说,BRESENHEM用到的是梯形加速度,我们需要计算梯形的各个表征值。

  float nominal_speed;              // 匀速运动速度

  float entry_speed;                // 从一个BLOCK进入到这个BLOCK的速度

  float max_entry_speed;            // 最大的进入速度

  float millimeters;                // BLOCK运动的实际mm距离

  uint8_t recalculate_flag;          // 重新计算梯度的FLAG

  uint8_t nominal_length_flag;        // 是否进入了匀速的FLAG

  第三部分:

实际梯形的各个参数计算

  uint32_t initial_rate;              // 梯形运动初始值 

  uint32_t final_rate;                // 梯形运动结束

  int32_t rate_delta;                //计算加速度

  uint32_t accelerate_until;          // 加速度阶段运动的距离

  uint32_t decelerate_after;          // 减速度阶段运行的距离

  uint32_t nominal_rate;              // 匀速阶段运行的距离

} block_t;

实际上,BLOCK的执行需要一定的时间,所以没有执行完成的BLOCK需要列队进行等待,所以需要用到调度器。

目前,3D打印机做开源的主要用到了Marlin固件,其实核心算法就是GRBL,加入了两轴材料挤出的步进电机轴,另外还用到了一个开源的温控PID算法,这个我们暂时用不上,不再考虑。

在找Marlin固件时发现了一个好的芯片,TC2100这颗IC卖出的价格在20元以上,而市面上用的1.5A电流的芯片大部分只卖到了4元左右,这颗IC的核心优势就是细分数,看了一下资料,也用到了他们的专利算法:一种新型的PWM算法,淘宝上卖出的模块价格在37元左右,其实还有不少的利润空间,可惜拿货估计有点麻烦,订单小了估计都不好拿货。

另外需要注意的是,初始化的参数是存放在EEPROM中的,GRBL也有一个EEPROM的函数,但是实际上我们定义了我们新的EEPROM函数,用到的是W24512,至于这一块如何移植,后文再介绍。

阅读全文

与改进的bresenham的算法相关的资料

热点内容
拆解汽车解压视频 浏览:593
新版百度云解压缩 浏览:588
android上下拉刷新 浏览:876
centos可执行文件反编译 浏览:836
林清玄pdf 浏览:270
黑马程序员java基础 浏览:283
awss3命令 浏览:358
百度店铺客户订单手机加密 浏览:500
钉钉班群文件夹怎么上传文件 浏览:749
人社app怎么解绑手机 浏览:101
caj文件夹打不开 浏览:475
什么app可以将电量变色 浏览:692
解放出你的解压抖音小游戏 浏览:346
什么方式解压比较好 浏览:267
erp是什么服务器 浏览:186
python中tmp 浏览:25
说明wpf加密过程 浏览:146
java读取list 浏览:704
iis7gzip压缩 浏览:41
有什么安卓机打吃鸡好 浏览:599