谁知道lineto画线的算法?(200分)

  • 主题发起人 主题发起人 ozj
  • 开始时间 开始时间
O

ozj

Unregistered / Unconfirmed
GUEST, unregistred user!
谁知道lineto画线的算法?包括粗线、细线,以便算出lineto所画的线下面所占用的
坐标,这样线移走时就能恢复底图。
 
我就知道没人能告诉我!!!help..........
 
留下mail,给你一个例子.
 
卷起千堆雪tyn:
我的email:ouyangzj@163.com
 
看看下面的例子,lineto经过的坐标不是很明显吗?
with Canvas do
begin
Rectangle(0, 0, 100, 100);
MoveTo(0, 0);
LineTo(100, 100);
MoveTo(0, 100);
LineTo(100, 0)
end;
 
要的是线所覆盖的每一个点。
我用Bresenham算法去模拟,可是细线、粗线模拟都有偏差,特别是粗线的头尾!
 
去接收,……
 
卷起千堆雪tyn:
已收到。
thank you for help,我将仔细研究一下。
 
看来我昨天买的两本“计算机图形学”又要浪费钱了,
实际问题很难在书上找到答案。
 
那种书只是一种工具,你可以在那里找到算法思想,真正解决问题,还是需要靠自己哦。
 
卷起千堆雪tyn:
程序原来是在每一次移动一条线时,先把画布填为白色,再把所有的线画一遍:
有致命弱点:
1、图必须足够小,小才不会闪。
2、不能有底图,我试加了底图,情况极差,闪得欢。
在实际中无用。
 
我的思想是,用lineto画一条线,在画之前先保存线所要经过的地方的素点,
当线移动时,再把保存的画回来就可保留底图。
 
PROGRAM Bresenham;

PROCEDURE DrawPixel (x,y: INTEGER);
BEGIN
WRITELN ('(x,y) = (',x:3,',',y:3,')')
END {DrawPixel};

PROCEDURE DrawLine (xStart,yStart, xEnd,yEnd: INTEGER);
{Bresenham's Line Algorithm. Byte, March 1988, pp. 249-253.}
VAR
a,b : INTEGER; {displacements in x and y}
d : INTEGER; {decision variable}
diag_inc : INTEGER; {d's increment for diagonal steps}
dx_diag : INTEGER; {diagonal x step for next pixel}
dx_nondiag : INTEGER; {nondiagonal x step for next pixel}
dy_diag : INTEGER; {diagonal y step for next pixel}
dy_nondiag : INTEGER; {nondiagonal y step for next pixel}
i : INTEGER; {loop index}
nondiag_inc: INTEGER; {d's increment for nondiagonal steps}
swap : INTEGER; {temporary variable for swap}
x,y : INTEGER; {current x and y coordinates}
BEGIN {DrawLine}
x := xStart; {line starting point}
y := yStart;
{Determine drawing direction and step to the next pixel.}
a := xEnd - xStart; {difference in x dimension}
b := yEnd - yStart; {difference in y dimension}
{Determine whether end point lies to right or left of start point.}
IF a < 0 {drawing towards smaller x values?}
THEN BEGIN
a := -a; {make 'a' positive}
dx_diag := -1
END
ELSE
dx_diag := 1;
{Determine whether end point lies above or below start point.}
IF b < 0 {drawing towards smaller x values?}
THEN BEGIN
b := -b; {make 'a' positive}
dy_diag := -1
END
ELSE
dy_diag := 1;
{Identify octant containing end point.}
IF a < b
THEN BEGIN
swap := a;
a := b;
b := swap;
dx_nondiag := 0;
dy_nondiag := dy_diag
END
ELSE BEGIN
dx_nondiag := dx_diag;
dy_nondiag := 0
END;
d := b + b - a; {initial value for d is 2*b - a}
nondiag_inc := b + b; {set initial d increment values}
diag_inc := b + b - a - a;
FOR i := 0 TO a DO BEGIN {draw the a+1 pixels}
DrawPixel (x,y);
IF d < 0 {is midpoint above the line?}
THEN BEGIN {step nondiagonally}
x := x + dx_nondiag;
y := y + dy_nondiag;
d := d + nondiag_inc {update decision variable}
END
ELSE BEGIN {midpoint is above the line; step diagonally}
x := x + dx_diag;
y := y + dy_diag;
d := d + diag_inc
END
END;
WRITELN;
READLN
END {DrawLine};

BEGIN
DrawLine (0,0, 10, 4);
DrawLine (0,0, 4, 10);
DrawLine (0,0, -4, 10);
DrawLine (0,0,-10, 4);
DrawLine (0,0,-10, -4);
DrawLine (0,0, -4,-10);
DrawLine (0,0, 4,-10);
DrawLine (0,0, 10, -4)
END {Bresenham}.
 
其实你可以考虑矢量的概念么.
比如你画了一条直线,你可以记录下线的起点和终点、颜色、粗细;
重画就OK.

其实你的问题归结起来就是UNDO和REDO的问题.
 
原来画的线怎样擦去,并保留底图,且我不想用notxor方法,因为当线为折线、粗线时notxor方法就不行,
另外和底图notxor也很难看。
 
用Bresenham算法去模拟,可是细线、粗线模拟都有偏差,特别是粗线的头尾!
 
一个最笨笨的方法 :
比如你在一副图上画了一条线,那么在这之前你可以建立一幅临时位图,将线覆盖的区域保存为
位图;在你想恢复时重载保存过的位图部分就OK

搜索一下以前的undo和redo,你会发现答案的.
 
要获得线所覆盖的区域的点的坐标才行啊,这是问题的关键。
其实,我可以用Bresenham算法来画线并记下每一点,问题是粗线的Bresenham算法
不好实现且起始点的处理较难,因此才想用lineto,可就是没法获得每一点的坐标。
 
要获得坐标还不容易,创建一个临时位图和原图异或比较一下就得到了象素坐标!
 
非常规方法 : 你就不能将线覆盖的整个方形区域保存么???虽然浪费了点。

好好看看UNDO和REDO的操作,有好处的。
 
后退
顶部