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

Тема в разделе "Delphi - FAQ", создана пользователем Pentium5, 16 окт 2011.

Статус темы:
Закрыта.
  1. Pentium5

    Pentium5 Member

    Регистрация:
    3 окт 2011
    Сообщения:
    9
    Симпатии:
    0
    Здравствуйте!
    Необходима помощь по созданию линии с помощью алгоритма Брезенхэма.
    Программа работает, но с полем получения линии возникают проблемы: при введении начальной и конечной координаты, линия не всегда рисуется, а если рисуется, то только по диагонали. Собственно вопрос: как это исправить, что бы линия всегда рисовалась правильно?
    На рисунке видно, что линия рисуется только так, в другом направлении рисоваться не хочет
    [​IMG]
    Программа в архиве.
     

    Вложения:

    • Brezenhemen.rar
      Размер файла:
      192,7 КБ
      Просмотров:
      13
  2. Vadik(R)

    Vadik(R) Well-Known Member

    Регистрация:
    12 дек 2007
    Сообщения:
    483
    Симпатии:
    0
    Странный какой-то Брезенхэм. Могу дать свой код (правда, на ассембелере), там у меня нормально линии рисуются.
     
  3. Pentium5

    Pentium5 Member

    Регистрация:
    3 окт 2011
    Сообщения:
    9
    Симпатии:
    0
    Код Ассамблера идёт на Дельфи?
     
  4. Vadik(R)

    Vadik(R) Well-Known Member

    Регистрация:
    12 дек 2007
    Сообщения:
    483
    Симпатии:
    0
    В 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]
     
  5. Pentium5

    Pentium5 Member

    Регистрация:
    3 окт 2011
    Сообщения:
    9
    Симпатии:
    0
    Спасибо, но мне всё-таки надо сдавать в коде Делфи.
     
  6. Vadik(R)

    Vadik(R) Well-Known Member

    Регистрация:
    12 дек 2007
    Сообщения:
    483
    Симпатии:
    0
    А по коду не можешь написать аналогичный на Delphi?
     
  7. Pentium5

    Pentium5 Member

    Регистрация:
    3 окт 2011
    Сообщения:
    9
    Симпатии:
    0
    К сожалению, с Ассамблером не знаком. Да и мой код как-то понятней.
     
Загрузка...
Статус темы:
Закрыта.

Поделиться этой страницей