Алгоритм Брезенхэма

Статус
Закрыто для дальнейших ответов.
03.10.2011
8
0
#1
Здравствуйте!
Необходима помощь по созданию линии с помощью алгоритма Брезенхэма.
Программа работает, но с полем получения линии возникают проблемы: при введении начальной и конечной координаты, линия не всегда рисуется, а если рисуется, то только по диагонали. Собственно вопрос: как это исправить, что бы линия всегда рисовалась правильно?
На рисунке видно, что линия рисуется только так, в другом направлении рисоваться не хочет

Программа в архиве.
 

Вложения

Vadik(R)

Well-known member
12.12.2007
469
0
#2
Странный какой-то Брезенхэм. Могу дать свой код (правда, на ассембелере), там у меня нормально линии рисуются.
 

Vadik(R)

Well-known member
12.12.2007
469
0
#4
В Delphi есть ассемблерные вставки, но у тебя вывод изображения на компонент, так что просто так его вставить не получится. А вот переписать код - можно :) Держи:<!--shcode--><pre><code class='asm'>stacksg segment para stack 'stack'
dw 100h dup(0)
stacksg ends

data segment
color db 0 ;Цвет отрезка
deltax dw 0 ;Разность x-координат отрезка
deltay dw 0 ;Разность y-координат отрезка
er dw 0 ;Ошибка
flag db 0 ;Флаг, равен 1, если deltax < deltay
signx dw 0 ;Знак разности x-координат отрезка
signy dw 0 ;Знак разности y-координат отрезка
x dw 0 ;Текущая x-координата
y dw 0 ;Текущая y-координата
x1 dw 0 ;Координата x начала отрезка
y1 dw 0 ;Координата y начала отрезка
x2 dw 0 ;Координата x конца отрезка
y2 dw 0 ;Координата y конца отрезка
data ends

code segment
assume cs: code, ds: data, ss: stacksg
sign proc near ;Вход - ax, выход в bx -1 или 1
mov bx, 1 ;Предполагаем, что число положительное
cmp ax, 0 ;Сравниваем число с нулем
jnl vihod1 ;Если не меньше, то на выход
mov bx, -1 ;Иначе число отрицательное
vihod1:
ret
sign endp

modul proc near ;Вход - ax, выход в ax -1 или 1
cmp ax, 0 ;Сравниваем число с нулем
jnl vihod2 ;Если оно не меньше, то на выход
neg ax ;Отрицаем число
vihod2:
ret
modul endp

line proc near
;deltax = |x2 - x1|
;signx - знак
mov ax, x2
sub ax, x1
call sign
mov signx, bx
call modul
mov deltax, ax
;deltay = |y2 - y1|
;signy - знак
mov ax, y2
sub ax, y1
call sign
mov signy, bx
call modul
mov deltay, ax
;Копируем начальные значения x и y, флаг flag = 0
mov ax, x1
mov x, ax
mov ax, y1
mov y, ax
;Предполагаем, что deltax >= deltay
mov flag, 0
;Сравниваем deltay с deltax
mov ax, deltax
cmp ax, deltay
jnl next1
;Если deltax < deltay, то меняем их местами
mov ax, deltax
mov bx, deltay
mov deltax, bx
mov deltay, ax
;Запоминаем, что deltax < deltay
mov flag, 1
next1:
;Вычисляем ошибку er = 2 * deltay - deltax
mov ax, deltay
mov er, ax
shl er, 1
mov ax, deltax
sub er, ax
;Цикл по столбцам (по строкам, если deltax < deltay)
mov cx, deltax
cloop:
;Выводим точку
mov al, color;Цвет
mov ah, 0ch;Код операции
xor bh, bh;Номер видеостраницы
push cx ;Запоминаем счетчик цикла
mov cx, x;x-координата точки
mov dx, y;y-координата точки
int 10h
pop cx ;Восстанавливаем счетчик цикла
;Если er < 0 (2 * er < deltax)
cmp er, 0
jl next2
;Уменьшаем ошибку er = er - 2 * deltax
mov ax, deltax
shl ax, 1
sub er, ax
;Проверяем deltax < deltay
cmp flag, 0
je else1
;Случай deltax < deltay
;Идём в следующую колонку к концу отрезка, так как накопилась ошибка
mov ax, signx
add x, ax
jmp next2
else1:
;Случай deltax >= deltay
;Идём в следующий столбец к концу отрезка, так как накопилась ошибка
mov ax, signy
add y, ax
next2:
;Проверяем deltax < deltay
cmp flag, 0
je else2
;Случай deltax < deltay
;Идём в следующий столбец к концу отрезка, как задумано по циклу
mov ax, signy
add y, ax
jmp next3
else2:
;Случай deltax >= deltay
;Идём в следующую колонку к концу отрезка, как задумано по циклу
mov ax, signx
add x, ax
next3:
;Вычисляем новое значение ошибки er = er + 2 * deltay
mov ax, deltay
shl ax, 1
add er, ax
;Продолжаем цикл
loop cloop
ret
line endp

begin proc far
push ds
xor ax, ax
push ax
mov ax, data
mov ds, ax
;Переход в графический режим 640 x 480, 16 цветов
mov ax, 12h
int 10h
;Задаем координаты и цвет первой прямой
mov color, 2
mov x1, 0
mov y1, 0
mov x2, 300
mov y2, 200
call line
;Задаем координаты и цвет второй прямой
mov color, 3
mov x1, 500
mov y1, 0
mov x2, 400
mov y2, 100
call line
;Чтение клавиши для задержки экрана
mov ah, 08h
int 21h
;Возвращаемся в текстовый режим 80 x 25, 16 цветов
mov ax, 0003h
int 10h
ret
begin endp
code ends
end begin[/CODE]
 
03.10.2011
8
0
#5
В Delphi есть ассемблерные вставки, но у тебя вывод изображения на компонент, так что просто так его вставить не получится. А вот переписать код - можно :) Держи:<!--shcode--><pre><code class='asm'>stacksg segment para stack 'stack'
dw 100h dup(0)
stacksg ends

data segment
color db 0;Цвет отрезка
deltax dw 0;Разность x-координат отрезка
deltay dw 0;Разность y-координат отрезка
er dw 0;Ошибка
flag db 0;Флаг, равен 1, если deltax < deltay
signx dw 0;Знак разности x-координат отрезка
signy dw 0;Знак разности y-координат отрезка
x dw 0;Текущая x-координата
y dw 0;Текущая y-координата
x1 dw 0;Координата x начала отрезка
y1 dw 0;Координата y начала отрезка
x2 dw 0;Координата x конца отрезка
y2 dw 0;Координата y конца отрезка
data ends

code segment
assume cs: code, ds: data, ss: stacksg
sign proc near;Вход - ax, выход в bx -1 или 1
mov bx, 1;Предполагаем, что число положительное
cmp ax, 0;Сравниваем число с нулем
jnl vihod1;Если не меньше, то на выход
mov bx, -1;Иначе число отрицательное
vihod1:
ret
sign endp

modul proc near;Вход - ax, выход в ax -1 или 1
cmp ax, 0;Сравниваем число с нулем
jnl vihod2;Если оно не меньше, то на выход
neg ax;Отрицаем число
vihod2:
ret
modul endp

line proc near
;deltax = |x2 - x1|
;signx - знак
mov ax, x2
sub ax, x1
call sign
mov signx, bx
call modul
mov deltax, ax
;deltay = |y2 - y1|
;signy - знак
mov ax, y2
sub ax, y1
call sign
mov signy, bx
call modul
mov deltay, ax
;Копируем начальные значения x и y, флаг flag = 0
mov ax, x1
mov x, ax
mov ax, y1
mov y, ax
;Предполагаем, что deltax >= deltay
mov flag, 0
;Сравниваем deltay с deltax
mov ax, deltax
cmp ax, deltay
jnl next1
;Если deltax < deltay, то меняем их местами
mov ax, deltax
mov bx, deltay
mov deltax, bx
mov deltay, ax
;Запоминаем, что deltax < deltay
mov flag, 1
next1:
;Вычисляем ошибку er = 2 * deltay - deltax
mov ax, deltay
mov er, ax
shl er, 1
mov ax, deltax
sub er, ax
;Цикл по столбцам (по строкам, если deltax < deltay)
mov cx, deltax
cloop:
;Выводим точку
mov al, color;Цвет
mov ah, 0ch;Код операции
xor bh, bh;Номер видеостраницы
push cx;Запоминаем счетчик цикла
mov cx, x;x-координата точки
mov dx, y;y-координата точки
int 10h
pop cx;Восстанавливаем счетчик цикла
;Если er < 0 (2 * er < deltax)
cmp er, 0
jl next2
;Уменьшаем ошибку er = er - 2 * deltax
mov ax, deltax
shl ax, 1
sub er, ax
;Проверяем deltax < deltay
cmp flag, 0
je else1
;Случай deltax < deltay
;Идём в следующую колонку к концу отрезка, так как накопилась ошибка
mov ax, signx
add x, ax
jmp next2
else1:
;Случай deltax >= deltay
;Идём в следующий столбец к концу отрезка, так как накопилась ошибка
mov ax, signy
add y, ax
next2:
;Проверяем deltax < deltay
cmp flag, 0
je else2
;Случай deltax < deltay
;Идём в следующий столбец к концу отрезка, как задумано по циклу
mov ax, signy
add y, ax
jmp next3
else2:
;Случай deltax >= deltay
;Идём в следующую колонку к концу отрезка, как задумано по циклу
mov ax, signx
add x, ax
next3:
;Вычисляем новое значение ошибки er = er + 2 * deltay
mov ax, deltay
shl ax, 1
add er, ax
;Продолжаем цикл
loop cloop
ret
line endp

begin proc far
push ds
xor ax, ax
push ax
mov ax, data
mov ds, ax
;Переход в графический режим 640 x 480, 16 цветов
mov ax, 12h
int 10h
;Задаем координаты и цвет первой прямой
mov color, 2
mov x1, 0
mov y1, 0
mov x2, 300
mov y2, 200
call line
;Задаем координаты и цвет второй прямой
mov color, 3
mov x1, 500
mov y1, 0
mov x2, 400
mov y2, 100
call line
;Чтение клавиши для задержки экрана
mov ah, 08h
int 21h
;Возвращаемся в текстовый режим 80 x 25, 16 цветов
mov ax, 0003h
int 10h
ret
begin endp
code ends
end begin[/CODE]
Спасибо, но мне всё-таки надо сдавать в коде Делфи.
 
Статус
Закрыто для дальнейших ответов.