两点一线,怎么实现??!!

happyhuangzy 2003-09-04 10:14:55
在C中,给定两个数据点,画出一条直线,怎么在程序中实现?多谢诸位!
...全文
193 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
sakurar 2003-09-04
  • 打赏
  • 举报
回复
最简单的用dda 算法
dda_line (xa, ya, xb, yb, c)

int xa, ya, xb, yb, c;

{

float delta_x, delta_y, x, y;

int dx, dy, steps, k;

dx=xb-xa;

dy=yb-ya;

if (abs(dx)>abs(dy)) steps=abs(dx);

else steps=abs (dy);

delta_x=(float)dx / (float)steps;

delta_y=(float)dy / (float)steps;

x=xa;

y=ya;

set_pixel(x, y, c);

for (k=1; k<=steps; k++)

{

x+=delta_x;

y+=delta_y;

set_pixel(x, y, c);

}

}


如果要求避免浮点运算,可用Bresenham算法


void line (x1, y1, x2, y2, c)

int x1, y1, x2, y2, c;

{

int dx;

int dy;

int x;

int y;

int p;

int const1;

int const2;

int inc;

int tmp;

dx=x2-x1;

dy=y2-y1;

if (dx*dy>=0) /*准备x或y的单位递变值。*/

inc=1;

else

inc=-1;

if (abs(dx)>abs(dy)){

if(dx<0){

tmp=x1; /*将2a, 3a象限方向*/

x1=x2; /*的直线变换到1a, 4a*/

x2=tmp;

tmp=y1; /*象限方向去*/

y1=y2;

dx=-dy;

dy=-dy;

}

p=2*dy-dx;

const1=2*dy; /*注意此时误差的*/

const2=2*(dy-dy); /*变化参数取值. */

x=x1;

y=y1;

set_pixel(x, y, c);

while (x<x2){

x++;

if (p<0)

p+=const1;

else{

y+=inc;

p+=const2;

}

set_piexl(x, y, c);

}

}

else {

if (dy<0){

tmp=x1; /* 将3b, 4b象限方向的*/

x1=x2; /*直线变换到2b, 1b */

x2=tmp; /*象限方向去. */

tmp=y1;

y1=y2;

dx=-dy;

dy=-dy;

}

p=2*dx-dy; /*注意此时误差的*/

const1=2*dx; /*变化参数取值. */

const2=2*(dx-dy);

x=x1;

y=y1;

set_pixel (x, y, c);

while (y<y2){

y++;

if(p<0)

p+=const1;

else{

x+=inc;

p+=const2;

set_pixel (x, y, c);

}

}

}



转自《计算机图形学》一书。
nobounded 2003-09-04
  • 打赏
  • 举报
回复
如果是win32 application的话,可以用api函数实现如:
MoveTo(hdc,point1.x,point1.y);
LineTo(hdc,point2.x,point2.y);
见MSDN,还有新函数
BOOL MoveToEx(
HDC hdc, // handle to device context
int X, // x-coordinate of new current position
int Y, // y-coordinate of new current position
LPPOINT lpPoint // pointer to old current position
);
也可以使用。
sakurar 2003-09-04
  • 打赏
  • 举报
回复
Bresenham算法

本算法由Bresenham在1965年提出。设直线从起点(x1, y1)到终点(x2, y2)。直线可表示为方程y=mx+b。其中b = y1 - m * x1,

m = (y2-y1)/(x2-x1) = dy / dx

我们的讨论先将直线方向限于1a象限(图2.1.1)在这种情况下,当直线光栅化时,x每次都增加1个单元,即

xi+1=xi+1

而y的相应增加应当小于1。






yi+1的位置选择yi-1=yi 或者 yi+1=yi+1


选择的原则是看精确值y与yi及yi+1的距离d1及d2的大小而定。计算式为:

y=m(xi+1)+b (2.1.1)

d1=y-yi (2.1.2)

d2=yi+1-y (2.1.3)

如果d1-d2>0,则yi+1=yi+1,否则yi+1=yi。因此算法的关键在于简便地求出d1-d2的符号。将式(2.1.1)、(2.1.2)、(2.1.3)代入d1-d2,得

d1-d2=2y-2yi-1=2 * (dy/dx)*(xi+1)-2yi+2b-1

用dx乘等式两边,并以Pi=dx(d1-d2)代入上述等式,得

Pi=2xidy-2yidx+2dy+dx(2b-1) (2.1.4)

d1-d2是我们用以判断符号的误差。由于在1a象限,dx总大于0,所以Pi仍旧可以用作判断符号的误差。Pi-1为:

Pi+1=Pi+2dy-2dx(yi+1-yi) (2.1.5)

误差的初值P1,可将x1, y1,和b代入式(2.1.4)中的xi, yi而得到:

P1=2dy-dx

综述上面的推导,第1a象限内的直线Bresenham算法思想如下:

 

1、画点(x1, y2); dx=x2-x1; dy=y2-y1;

计算误差初值P1=2dy-dx; i=1;

2、求直线的下一点位置:

xi+1=xi+1;

if Pi>0 则yi+1=yi+1;

否则yi+1=yi;

3、画点(xi+1, yi-1);

4、求下一个误差Pi+1;

if Pi>0 则Pi+1=Pi+2dy-2dx;

否则Pi+1=Pi+2dy;

5、i=i+1; if i<dx+1则转2;否则end。





Bresenham算法的优点是:

1、不必计算直线之斜率,因此不做除法;
2、不用浮点数,只用整数;
3、只做整数加减法和乘2运算,而乘2运算可以用硬件移位实现。



Bresenham算法速度很快,并适于用硬件实现。

happyhuangzy 2003-09-04
  • 打赏
  • 举报
回复
set_pixel()是C库函数吗?我在C库函数中没找到有这个函数
happyhuangzy 2003-09-04
  • 打赏
  • 举报
回复
请解释一下Bresenham的基本思想,不胜感激!
蝎子i软件 2003-09-04
  • 打赏
  • 举报
回复
set_pixel()用于设置像素点的颜色。
happyhuangzy 2003-09-04
  • 打赏
  • 举报
回复
还有一个菜鸟问题,set_piexl()的作用是什么??
在我这个画直线的程序中,不能inlcude C库函数,所以,怎么编写类似于set_piexl()的函数??
多谢不谢!
happyhuangzy 2003-09-04
  • 打赏
  • 举报
回复
tks up!
能不能讲一下该程序算法的基本思想,再次谢谢!

69,382

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧