1. Если вы только начинаете программировать на ассемблере и не знаете с чего начать, тогда попробуйте среду разработки ASM Visual IDE
    (c) на правах рекламы
    Скрыть объявление

Рисование окружности

Тема в разделе "WASM.DOS/BIOS/Vesa/ports", создана пользователем Mikl___, 24 дек 2016.

  1. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    2.764

    Рисование окружности

    Построить окружность несложно. У окружности координаты любой точки относительно ее центра вычисляются из соотношения [math]R^{2}=X^{2}+Y^{2}[/math], где [math]R[/math] радиус окружности. С точки зрения программирования достаточно нарисовать [math]\frac{1}{8}[/math] часть окружности, а симметрия закончит дело. В языках программирования высокого уровня существует специальная функция CIRCLE, которая строит окружность либо, вычисляя синус, либо, двигаясь например по оси [math]X[/math] вычисляет на каждом шаге координату [math]Y[/math] по формуле [math]\sqrt{R^{2}-X^{2}}[/math]. В языке ассемблера для вычисления квадратного корня или функции синуса пришлось бы использовать обращение к сопроцессору, а такая программа с точки зрения ассемблера работает непозволительно долго. Подумаем, как нам реализовать более быстрый метод рисования окружностей используя только целочисленную арифметику, ведь на экране можно выводить точку только туда, где находится люминофор, а не между люминофорами, или смещать точку на долю микрона вправо или влево. Пусть центр окружности находится в точке (0, 0) [math]Y=R=100[/math] и [math]X=0[/math] по формуле [math]Y^{2}[/math] равен [math]R^{2}-X^{2}[/math]. По мере движения по оси [math]X[/math] мы должны выяснить, когда нам необходимо уменьшить [math]Y[/math]. Это нужно сделать если отклонение от [math]Y[/math] будет больше 0,5 величины люминофора, то есть больше должна засвечиваться соседняя точка. Вычисляем квадрат отклонения: [math](Y-0,5)^{2}=Y^{2}-Y+0,25[/math]. Выражение [math]Y^{2}-Y[/math] вычисляется в целых числах, а [math]0,25[/math] игнорируем. Если разность [math]R^{2}-X^{2}[/math] больше чем [math]Y^{2}-Y[/math] необходимо уменьшить [math]Y[/math] на единицу и опять пересчитать ту величину, когда необходимо будет снова изменить [math]Y[/math]
    и так в цикле. Вы выводите [math]N[/math] точек, где [math]N[/math] вычисляется из значения [math]L=2\pi\cdot R[/math]. Так как Вам надо нарисовать [math]\frac{1}{8}[/math] окружности [math]N=\frac{L}{8}=\frac{R\pi}{4}\approx \frac{11\cdot R}{14}[/math]
    Код (ASM):
    1. .286
    2. .model tiny
    3. .code
    4. RADIUS EQU 99 ;рисуем окружность с радиусом 99
    5. RADIUS2 EQU RADIUS*RADIUS ;квадрат радиуса
    6. DIAMETR EQU RADIUS*2 ;диаметр окружности
    7. N EQU 11*RADIUS/14;количество точек на 1/8
    8. COLOR EQU 10 ;цвет окружности
    9. ORG 100h
    10. start: MOV AH,0Fh ;узнать номер текущего видеорежима
    11. INT 10h
    12. MOV VIDEOR,AL ;запомним текущий видеорежим
    13. MOV AX,13h;установить видеорежим 320х200х256
    14. INT 10h
    15. PUSH 0A000h;установить регистр ES на сегмент
    16. POP ES ; видеопамяти
    17. XOR BP,BP ;будем увеличивать X и Y
    18. MOV Y,RADIUS-1 ;координаты X=0 и Y=R
    19. CALL DRAW_OCT1 ;рисуем восьмушку окружности
    20. MOV BP,RADIUS-1 ;координата X=2*R
    21. MOV Y,0 ;координата Y=0
    22. CALL DRAW_OCT2 ;рисуем восьмушку окружности
    23. NEG DELTA_X ;увеличиваем Y и уменьшаем X
    24. MOV Y,RADIUS
    25. MOV BP,DIAMETR ;координаты Y=R и X=2*R
    26. CALL DRAW_OCT1 ;рисуем восьмушку окружности
    27. MOV BP,RADIUS ;координата X=R
    28. MOV Y,0 ;координата Y=0
    29. CALL DRAW_OCT2 ;рисуем восьмушку окружности
    30. NEG DELTA_Y ;уменьшаем координаты Y и X
    31. MOV Y,RADIUS ;координата Y=R
    32. MOV BP,DIAMETR ;координата X=2*R
    33. CALL DRAW_OCT1 ;рисуем восьмушку окружности
    34. MOV BP,RADIUS ;координата X=R
    35. MOV Y,DIAMETR ;координата Y=2*R
    36. CALL DRAW_OCT2 ;рисуем восьмушку окружности
    37. NEG DELTA_X ; уменьшаем Y и увеличиваем X
    38. XOR BP,BP ;координата X=0
    39. MOV Y,RADIUS ;координата Y=R
    40. CALL DRAW_OCT1 ;рисуем восьмушку окружности
    41. MOV BP,RADIUS ;координата X=R
    42. MOV Y,DIAMETR ;координата Y=2*R
    43. CALL DRAW_OCT2 ;рисуем восьмушку окружности
    44. XOR AX,AX ;ожидание нажатия любой клавиши
    45. INT 16h
    46. MOV AX,WORD PTR VIDEOR;восстановление видеорежима
    47. INT 10h
    48. RET ;выход из программы
    49. PROC DELTA_CALC ;рассчитаем ошибку накопления
    50. MOV BX,AX ;в AX значение координаты X или Y
    51. DEC AX ;вычислим (Y+0,5)2 » Y2+Y
    52. MUL AX ;или (X+0,5)2 » X2+X
    53. ADD AX,BX
    54. MOV DELTA,AX ;и поместим это значение в DELTA
    55. RET
    56. ENDP
    57. ;процедура прорисовки 1/8 окружности с вычислением
    58. PROC DRAW_OCT1 ; координаты X
    59. MOV AX,Y
    60. SHL AX,6 ;должно быть DI=Y*320, но для умножения
    61. MOV DI,AX ;на 320 используем сдвиги, AX= Y*64,
    62. SHL AX,2 ;сохраним AX в DI и умножим Y*64 на 4
    63. ADD DI,AX ;DI=Y*(256+64)=Y*320.
    64. MOV AX,BP
    65. SUB AX,RADIUS ;BP=X AX=R-X
    66. CALL DELTA_CALC ;расчет ошибки накопления по X
    67. MOV CX,N
    68. CIRC1: MOV AX,Y
    69. SUB AX,RADIUS ;AX=Y-R
    70. MUL AX
    71. NEG AX
    72. ADD AX,RADIUS2 ;AX=R2-Y2
    73. CMP DELTA,AX ;сравнить текущий X2=R2-Y2 с ошибкой
    74. JBE A3 ;накопления, если меньше, увеличиваем или
    75. ADD BP,DELTA_X;уменьшаем только Y, иначе
    76. MOV AX,BP;увеличиваем или уменьшаем еще и X и
    77. SUB AX,RADIUS; вычисляем новую ошибку накопления
    78. CALL DELTA_CALC
    79. A3: CMP DELTA_Y,1
    80. JNE A1
    81. ADD DI,320
    82. JMP SHORT A2
    83. A1: SUB DI,320
    84. A2: MOV BYTE PTR ES:[DI][BP],COLOR;выводим точку на
    85. MOV AX,DELTA_Y; экран
    86. ADD Y,AX
    87. LOOP CIRC1 ;повторяем цикл
    88. RET
    89. ENDP
    90. ;процедура прорисовки 1/8 окружности с вычислением
    91. PROC DRAW_OCT2 ; координаты X
    92. MOV AX,Y
    93. SHL AX,6 ;должно быть DI=Y*320, но для умножения
    94. MOV DI,AX ;на 320 используем сдвиги, AX= Y*64,
    95. SHL AX,2 ;сохраним AX в DI и умножим Y*64 на 4
    96. ADD DI,AX ;DI=Y*(256+64)=Y*320.
    97. MOV AX, Y
    98. SUB AX,RADIUS
    99. CALL DELTA_CALC
    100. MOV CX,N
    101. CIRC2: MOV AX,BP
    102. SUB AX,RADIUS
    103. MUL AX
    104. NEG AX
    105. ADD AX,RADIUS2 ;AX=R^2-(X-R)^2
    106. CMP DELTA,AX
    107. JBE A5
    108. MOV AX,DELTA_Y
    109. ADD Y,AX
    110. MOV AX,Y
    111. SUB AX,RADIUS
    112. CALL DELTA_CALC
    113. CMP DELTA_Y,1
    114. JNE A4
    115. ADD DI,320
    116. JMP SHORT A5
    117. A4: SUB DI,320
    118. A5: ADD BP,DELTA_X
    119. MOV BYTE PTR ES:[DI][BP],COLOR
    120. LOOP CIRC2
    121. RET
    122. ENDP
    123. VIDEOR DB 0,0 ;значение текущего видеорежима
    124. DELTA DW 0 ;ошибка накопления
    125. DELTA_X DW 1 ;смещение по оси X
    126. DELTA_Y DW 1 ;смещение по оси Y
    127. Y DW 0 ;координата Y
    128. END start
     
    Последнее редактирование: 24 дек 2016
    >Quiet Snow< нравится это.
  2. _edge

    _edge Well-Known Member

    Публикаций:
    1
    Регистрация:
    29 окт 2004
    Сообщения:
    576
    Адрес:
    Russia
    Рисование окр-ти на Freebasic (язык так себе, лучше уж Purebasic применять, а еще лучше ламповую Сишечку); привожу только для того, чтобы стала ясна логика рисования.

    Код (Text):
    1. dim as ULONGINT X=200,Y=200,R=100,x1,y1,a,b,r1
    2. screenres 640,480,32,,0
    3.  
    4.  
    5. for y1 = Y-R to Y+R
    6.    for x1 = X-R to X+R
    7.  
    8. a=y1-Y
    9. b=x1-X
    10. r1=r-1
    11.  
    12. if (a*a+b*b<=R*R AND a*a+b*b>=r1*r1) then pset(x1,y1),rgb(255,255,255)
    13.  
    14.    next x1
    15. next y1
    16.  
    17. sleep
    можно задать толщину, если поменять r1=r-1 на r1=r-2

    ---

    Прикреплю свою граф. библиотеку для mode13
    (комментариев почти нет, к сожалению), там тоже есть рисование круга.

    Компилировать: tasm /m2 rt3.asm и tlink /t rtl3.obj
     

    Вложения:

    • asm.zip
      Размер файла:
      2,9 КБ
      Просмотров:
      175
    Последнее редактирование: 24 дек 2016
  3. xcode

    xcode Member

    Публикаций:
    0
    Регистрация:
    8 апр 2007
    Сообщения:
    106
    _edge, у вас что полный перебор всех точек матрицы и для каждой проверяется принадлежит ли она окружности или нет? Это еще для закраски фигур может и годится а для однопиксельных контуров слишком накладно.
     
  4. _edge

    _edge Well-Known Member

    Публикаций:
    1
    Регистрация:
    29 окт 2004
    Сообщения:
    576
    Адрес:
    Russia
    Да, верно, полный перебор.
     
  5. Indy_

    Indy_ Well-Known Member

    Публикаций:
    4
    Регистрация:
    29 апр 2011
    Сообщения:
    2.602
    Где это запускать, поставить дос, это что прикол какой то ?
     
  6. _edge

    _edge Well-Known Member

    Публикаций:
    1
    Регистрация:
    29 окт 2004
    Сообщения:
    576
    Адрес:
    Russia
    Нет, дос ставить не нужно.

    Вот досбокс, в папку Virtual можно подкладывать файлы, это рабочая папка.
    Стартовать через dn.bat

    В оригинале там еще вин3.1 была, убрал.

    https://yadi.sk/d/2HXdYybb34tCfk пароль 1