Рисование окружностиПостроить окружность несложно. У окружности координаты любой точки относительно ее центра вычисляются из соотношения [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): .286 .model tiny .code RADIUS EQU 99 ;рисуем окружность с радиусом 99 RADIUS2 EQU RADIUS*RADIUS ;квадрат радиуса DIAMETR EQU RADIUS*2 ;диаметр окружности N EQU 11*RADIUS/14;количество точек на 1/8 COLOR EQU 10 ;цвет окружности ORG 100h start: MOV AH,0Fh ;узнать номер текущего видеорежима INT 10h MOV VIDEOR,AL ;запомним текущий видеорежим MOV AX,13h;установить видеорежим 320х200х256 INT 10h PUSH 0A000h;установить регистр ES на сегмент POP ES ; видеопамяти XOR BP,BP ;будем увеличивать X и Y MOV Y,RADIUS-1 ;координаты X=0 и Y=R CALL DRAW_OCT1 ;рисуем восьмушку окружности MOV BP,RADIUS-1 ;координата X=2*R MOV Y,0 ;координата Y=0 CALL DRAW_OCT2 ;рисуем восьмушку окружности NEG DELTA_X ;увеличиваем Y и уменьшаем X MOV Y,RADIUS MOV BP,DIAMETR ;координаты Y=R и X=2*R CALL DRAW_OCT1 ;рисуем восьмушку окружности MOV BP,RADIUS ;координата X=R MOV Y,0 ;координата Y=0 CALL DRAW_OCT2 ;рисуем восьмушку окружности NEG DELTA_Y ;уменьшаем координаты Y и X MOV Y,RADIUS ;координата Y=R MOV BP,DIAMETR ;координата X=2*R CALL DRAW_OCT1 ;рисуем восьмушку окружности MOV BP,RADIUS ;координата X=R MOV Y,DIAMETR ;координата Y=2*R CALL DRAW_OCT2 ;рисуем восьмушку окружности NEG DELTA_X ; уменьшаем Y и увеличиваем X XOR BP,BP ;координата X=0 MOV Y,RADIUS ;координата Y=R CALL DRAW_OCT1 ;рисуем восьмушку окружности MOV BP,RADIUS ;координата X=R MOV Y,DIAMETR ;координата Y=2*R CALL DRAW_OCT2 ;рисуем восьмушку окружности XOR AX,AX ;ожидание нажатия любой клавиши INT 16h MOV AX,WORD PTR VIDEOR;восстановление видеорежима INT 10h RET ;выход из программы PROC DELTA_CALC ;рассчитаем ошибку накопления MOV BX,AX ;в AX значение координаты X или Y DEC AX ;вычислим (Y+0,5)2 » Y2+Y MUL AX ;или (X+0,5)2 » X2+X ADD AX,BX MOV DELTA,AX ;и поместим это значение в DELTA RET ENDP ;процедура прорисовки 1/8 окружности с вычислением PROC DRAW_OCT1 ; координаты X MOV AX,Y SHL AX,6 ;должно быть DI=Y*320, но для умножения MOV DI,AX ;на 320 используем сдвиги, AX= Y*64, SHL AX,2 ;сохраним AX в DI и умножим Y*64 на 4 ADD DI,AX ;DI=Y*(256+64)=Y*320. MOV AX,BP SUB AX,RADIUS ;BP=X AX=R-X CALL DELTA_CALC ;расчет ошибки накопления по X MOV CX,N CIRC1: MOV AX,Y SUB AX,RADIUS ;AX=Y-R MUL AX NEG AX ADD AX,RADIUS2 ;AX=R2-Y2 CMP DELTA,AX ;сравнить текущий X2=R2-Y2 с ошибкой JBE A3 ;накопления, если меньше, увеличиваем или ADD BP,DELTA_X;уменьшаем только Y, иначе MOV AX,BP;увеличиваем или уменьшаем еще и X и SUB AX,RADIUS; вычисляем новую ошибку накопления CALL DELTA_CALC A3: CMP DELTA_Y,1 JNE A1 ADD DI,320 JMP SHORT A2 A1: SUB DI,320 A2: MOV BYTE PTR ES:[DI][BP],COLOR;выводим точку на MOV AX,DELTA_Y; экран ADD Y,AX LOOP CIRC1 ;повторяем цикл RET ENDP ;процедура прорисовки 1/8 окружности с вычислением PROC DRAW_OCT2 ; координаты X MOV AX,Y SHL AX,6 ;должно быть DI=Y*320, но для умножения MOV DI,AX ;на 320 используем сдвиги, AX= Y*64, SHL AX,2 ;сохраним AX в DI и умножим Y*64 на 4 ADD DI,AX ;DI=Y*(256+64)=Y*320. MOV AX, Y SUB AX,RADIUS CALL DELTA_CALC MOV CX,N CIRC2: MOV AX,BP SUB AX,RADIUS MUL AX NEG AX ADD AX,RADIUS2 ;AX=R^2-(X-R)^2 CMP DELTA,AX JBE A5 MOV AX,DELTA_Y ADD Y,AX MOV AX,Y SUB AX,RADIUS CALL DELTA_CALC CMP DELTA_Y,1 JNE A4 ADD DI,320 JMP SHORT A5 A4: SUB DI,320 A5: ADD BP,DELTA_X MOV BYTE PTR ES:[DI][BP],COLOR LOOP CIRC2 RET ENDP VIDEOR DB 0,0 ;значение текущего видеорежима DELTA DW 0 ;ошибка накопления DELTA_X DW 1 ;смещение по оси X DELTA_Y DW 1 ;смещение по оси Y Y DW 0 ;координата Y END start
Рисование окр-ти на Freebasic (язык так себе, лучше уж Purebasic применять, а еще лучше ламповую Сишечку); привожу только для того, чтобы стала ясна логика рисования. Код (Text): dim as ULONGINT X=200,Y=200,R=100,x1,y1,a,b,r1 screenres 640,480,32,,0 for y1 = Y-R to Y+R for x1 = X-R to X+R a=y1-Y b=x1-X r1=r-1 if (a*a+b*b<=R*R AND a*a+b*b>=r1*r1) then pset(x1,y1),rgb(255,255,255) next x1 next y1 sleep можно задать толщину, если поменять r1=r-1 на r1=r-2 --- Прикреплю свою граф. библиотеку для mode13 (комментариев почти нет, к сожалению), там тоже есть рисование круга. Компилировать: tasm /m2 rt3.asm и tlink /t rtl3.obj
_edge, у вас что полный перебор всех точек матрицы и для каждой проверяется принадлежит ли она окружности или нет? Это еще для закраски фигур может и годится а для однопиксельных контуров слишком накладно.
Нет, дос ставить не нужно. Вот досбокс, в папку Virtual можно подкладывать файлы, это рабочая папка. Стартовать через dn.bat В оригинале там еще вин3.1 была, убрал. https://yadi.sk/d/2HXdYybb34tCfk пароль 1