Thuật toán Breseham
Trang 1Thuật toán vẽ đoạn thẳng của
Breseham
Nguyễn Thế Anh
Bài toán vẽ đoạn thẳng khi cho trước hai điểm p1(x1,y1), p2(x2,y2), chắc chắn chúng ta ai cũng nghĩ quá đơn giản có gì mà phải xét, bởi lẽ về mặt thao tác người ta chỉ cần nối hai điểm lại là xong, trong máy tính bạn chỉ làm mỗi việc sử dụng lệnh gọi thủ tục Line(p1, p2) Thực tế thủ tục Line làm việc như thế nào ít ai để ý Thực ra khó khăn lớn nhất của bài toán vẽ đoạn thẳng trên máy tính là người ta phải vẽ mọi đoạn thẳng mà các điểm của nó chỉ gồm các toạ độ nguyên Trong toán học điều này không luôn luôn đúng Vì vậy trên máy tính diễn tả một đoạn thẳng bất kỳ bằng tập các điểm có toạ độ nguyên sai khác với đường thẳng thật ít nhất.Thực tế thủ tục Line không kẻ đoạn thẳng mà tô lần lượt các điểm ảnh (pixel) có toạ độ nguyên bằng một màu nào đó, tập các điểm ảnh này được coi là đoạn thẳng Mấu chốt của bài toán là như vậỵ Thuật toán Bresenham được coi là thuật toán vẽ đoạn thẳng tốt nhất, nó được coi là thuật toán kinh điển và thủ tục Line trong thư viện các chương trình đêu sử dụng thuật toán nàỵ Tư tưởng thuật toán của Bresenham là giả sử đã chọn được điểm ảnh thứ Pi của đoạn thẳng, ta bắt đầu chọn điểm ảnh Pi+1 Điểm ảnh Pi+1 có thể lấy Si+1 hoặc Ti+1 tuỳ thuộc vào quan hệ của đoạn s và t Nếu s>t sẽ chọn Si+1, ngược lại chọn Ti+1 (xem hình H2)
Bây giờ chúng ta chính xác hoá tư tưởng nàỵ
Ta bắt đầu bằng cách xét đường thẳng có hệ số góc nằm trong khoảng (0,1] vì các điểm trên màn hình được biểu diễn bởi các toạ độ nguyên nên ta cho x tăng theo bước nhảy đơn
vị từ x1 đến x2 Giả sử trên hình vẽ điểm (x[i],y[i]) là điểm nằm trên đoạn thẳng đã được
vẽ và cho x[i] tăng thêm 1 để vẽ điểm tiếp theo và giá trị của y ứng với x[i]+1 ta nên chọn
là y[i] hay y[i]+1, giá trị đúng của y=m(x[i]+1)+b như vậy ta sẽ tuỳ xem y[i] hay y[i]+1 gần y(=m(x[i]+1)+b) hơn thì ta sẽ chọn giá trị đó Ta xét các khoảng cách:
Khoảng cách giữa y và y[i]: d1=y-y[i]=m(x[i]+1)+b-y[i]
Khoảng cách giữa y[i]+1 và y: d2=y[i]+1-y=y[i]+1-m(x[i]+1)-b
Hiệu giữa hai khoảng cách này là: d1-d2=2m(x[i]+1)-2y[i]+2b-1
thay m=dy/dx ta có d1-d2=2(dy/dx)(x[i]+1)-2y[i]+2b-1
nên p[i]=dx(d1-d2)=2dỵx[i]+2dy-2dx.y[i]+2dx.b-dx =2dỵx[i]-2dx.y[i]+2dy+dx(2b-1)
Hay p[i]=2dỵx[i]-2dx.y[i]+c với c=2dy+dx(2b-1) (1)
thay i=1 ta có p[1]=2dỵx1-2dỵy1+c=2dy-dx
Nếu p[i]<0 nghĩa là y[i] gần đường thẳng hơn y[i]+1 và ta chọn y[i+1]=y[i] ngược lại ta chọn y[i+1]=y[i]+1
Công thức (1) có thể được giản lược bằng cách liên hệ với điểm
(x[i+1],y[i+1]) tiếp theo, khi đó p[i+1]=2dỵx[i+1]-2dx.y[i+1]+c (2)
Trừ (2) cho (1) ta có:
p[i+1]-p[i]=2dy(x[i+1]-x[i])-2dx(y[i+1]-y[i]) mà x[i+1]=x[i]+1 nên
p[i+1]=p[i]+2dy-2dx(y[i+1]-y[i])
Mà nếu p[i]<0 thì y[i+1] tiếp theo sẽ được chọn là y[i], nghĩa là y[i+1]=y[i] nên p[i+1]=p[i]+2dy=p[i]+const1 với const1=2dy ngược lại chọn y[i+1]=y[i]+1 nên p[i+1]=p[i]+2(dy-dx)=p[i]+const2 vớiconst2=2(dy-dx)
Trang 2Và thuật toán vẽ đường thẳng của Presenham trong trường hợp hệ số góc nằm trong khoảng (0,1] như sau:
1 Nếu x1>x2 Thì ta hoán vị 2 điểm (x1,y1) và (x2,y2)
2 Đặt dx:=Abs(x2-x1); dy:=Abs(y2-y1);
p:=2*dy-dx; const1:=2*dy; const2:=2*(dy-dx);
3 Đặt x:=x1; y:=y1;
4 vẽ điểm(x,y);
5 Tăng x lên 1 đơn vị
6 Nếu p<0 Thì p:=p+const1 và giữ nguyên y
Ngược lại p:=p+const2 va tăng y lên 1 đơn vị;
7 Kiểm tra xem x còn ≤ x2 không nếu còn quay lên bước 4 ngược lại kết thúc
8 Kết thúc
Procedure Line_(x1,y1,x2,y2: Integer);
Var
x,y,tg,dx,dy,const1,const2,p: Integer;
mau: Byte;
Begin
If x1>x2 Then
Begin
tg:=x1; x1:=x2; x2:=tg;
tg:=y1; y1:=y2; y2:=tg;
End;
dx:=Abs(x2-x1); dy:=Abs(y2-y1);
p:=2*dy-dx; const1:=2*dy;
const2:=2*(dy-dx);
mau:=GetColor;
x:=x1; y:=y1;
While x≤x2 Do
Begin
Putpixel(x,y,mau);
Inc(x);
If p<0 Then p:=p+const1
Else
Begin Inc(y); p:=p+const2; End;
End;
End;