2015-07-22 2 views
0

Я хотел бы нарисовать идеально заполненный круг (диск) в сборе в режиме 320x200 с радиусом 100 пикселей. Какой самый быстрый/простой способ?Что является самым простым способом нарисовать полностью заполненный круг (диск) в сборке?

(*: Я имею в виду диск полностью заполнен, когда его цвет, например, постоянный белый и не имеет никаких черных точек в нем.)

+0

Нарисуйте контур, а затем заливать заполнить круг. Это не учебный сайт по графическому программированию, поэтому ознакомьтесь с тем, как это сделать, и попытайтесь реализовать их самостоятельно. Если вы столкнулись с конкретной проблемой с кодом, который вы пишете, задайте вопрос об этом. – Michael

+1

Даже проще всего проследить только половину контура круга и зеркально отобразить его по горизонтали. То есть для каждой точки '-x, y' нарисуйте горизонтальную линию от' -x, y' до 'x, y'. – Michael

+0

Идеально для меня означает сглаживание по краям. – stark

ответ

1

Если по быстрым вы имеете в виду быстрое писать, вот простое решение для DOS ,

Он не использует службу DOS, кроме выхода.
Он предназначен для создания COM-файла (необработанный вывод с помощью NASM в порядке, просто переименуйте его с расширением COM).

BITS 16 

ORG 100h 

push 0a000h   ;Video memory graphics segment 
pop es 

mov ax, 0013h   ;[email protected] 
int 10h 


push 09h    ;Blue 
push 159    ;cX 
push 99    ;cY 
push 60    ;Radius 
call drawFilledCircle 

;Wait for a key 
xor ah, ah 
int 16h 

;Restore text mode 
mov ax, 0003h 
int 10h 

;Return 
mov ax, 4c00h 
int 21h 


;Color 
;cX 
;cY 
;R 
drawFilledCircle: 
push bp 
mov bp, sp 

sub sp, 02h 

mov cx, WORD [bp+04h] ;R 

mov ax, cx    
mul ax     ;AX = R^2 
mov WORD [bp-02h], ax ;[bp-02h] = R^2 



mov ax, WORD [bp+06h] 
sub ax, cx    ;i = cY-R 
mov bx, WORD [bp+08h] 
sub bx, cx    ;j = cX-R 

shl cx, 1 
mov dx, cx    ;DX = Copy of 2R 

.advance_v: 
push cx 
push bx 

mov cx, dx 

.advance_h: 
    ;Save values 
    push bx 
    push ax 
    push dx 

    ;Compute (i-y) and (j-x) 
    sub ax, WORD [bp+06h] 
    sub bx, WORD [bp+08h] 

    mul ax     ;Compute (i-y)^2 

    push ax 
    mov ax, bx    
    mul ax 
    pop bx     ;Compute (j-x)^2 in ax, (i-y)^2 is in bx now 

    add ax, bx    ;(j-x)^2 + (i-y)^2 
    cmp ax, WORD [bp-02h] ;;(j-x)^2 + (i-y)^2 <= R^2 

    ;Restore values before jump 
    pop dx 
    pop ax 
    pop bx 

    ja .continue   ;Skip pixel if (j-x)^2 + (i-y)^2 > R^2 

    ;Write pixel 
    push WORD [bp+0ah] 
    push bx 
    push ax 
    call writePx 


.continue: 

    ;Advance j 
    inc bx 
loop .advance_h 

;Advance i 
inc ax 


pop bx   ;Restore j 
pop cx   ;Restore counter 

loop .advance_v 

add sp, 02h 


pop bp 
ret 08h 



;Color 
;X 
;Y 
writePx: 
push bp 
mov bp, sp 

push ax 
push bx 

mov bx, WORD [bp+04h] 
mov ax, bx 
shl bx, 6 
shl ax, 8 
add bx, ax  ;320 = 256 + 64 

add bx, WORD [bp+06h] 
mov ax, WORD [bp+08h] 

;TODO: Clip 

mov BYTE [es:bx], al 

pop bx 
pop ax 

pop bp 
ret 06h 

Это просто обычная техника для записи плоских фигур с заданными параметрами, это называется растеризацией.

Учитывая центр С (х, у) и радиус R окружности, алгоритм, как следует

1. For i = y-R to y+R 
1.1 For j = x-R to x+R 
1.1.1  If (i-y)^2 + (j-x)^2 <= R^2 Then 
1.1.1.1  DrawPixel(j, i) 
1.1.1  End if 
1.1 End For 
1. End For 

Это не оптимизировано для скорости, при все!
Я действительно создаю несколько процедур для ясности. Также я использую стек много.

ПримечаниеwritePx не обрезает координаты!


Если вы хотите ускорить то, что вам нужно, чтобы быть более конкретным по вашему требованию.
Например, радиус всегда зафиксирован? Если да, вы можете использовать блок памяти, который кодирует четверть круга, что-то вроде этого

0 0 0 0 0 1 1 1 
0 0 0 1 1 1 1 1 
0 0 1 1 1 1 1 1 
0 1 1 1 1 1 1 1 
0 1 1 1 1 1 1 1 
0 1 1 1 1 1 1 1 
1 1 1 1 1 1 1 1 
1 1 1 1 1 1 1 1 

Где каждый цифры могут быть немного или байт в зависимости от вашей скорости против ограничений памяти.
Затем вы можете скопировать этот блок непосредственно в видеопамять или использовать ее в качестве шаблона (вид технологии цветной клавиши).
Для печати остальных трех четвертей круга просто играть со счетчиками.

Если радиус не фиксирован вы можете увеличить приведенный выше код на

  • Встраивание функции называют
  • Избегайте использования стека как можно больше
  • Не вычислить расстояние в каждый цикл, но вычислять его из предыдущего значения, используя базовое исчисление.
  • Вычислите больше одного пикселя за раз и объедините записи.
+0

Awesome. Благодарю. Это то, что я искал. Много хороших идей. – Fract

-1

Нашли это как рисовать круг. Извините, его не заполнили.Читать всю статью здесь: http://groups.csail.mit.edu/graphics/classes/6.837/F98/Lecture6/circle.html

//Circle 
public void circleMidpoint(int xCenter, int yCenter, int radius, Color c) 
{ 
    int pix = c.getRGB(); 
    int x = 0; 
    int y = radius; 
    int p = (5 - radius*4)/4; 

    circlePoints(xCenter, yCenter, x, y, pix); 
    while (x < y) { 
     x++; 
     if (p < 0) { 
      p += 2*x+1; 
     } else { 
      y--; 
      p += 2*(x-y)+1; 
     } 
     circlePoints(xCenter, yCenter, x, y, pix); 
    } 
} 

    //pixel plotter 

    private final void circlePoints(int cx, int cy, int x, int y, int pix) 
{ 
    int act = Color.red.getRGB(); 

    if (x == 0) { 
     raster.setPixel(act, cx, cy + y); 
     raster.setPixel(pix, cx, cy - y); 
     raster.setPixel(pix, cx + y, cy); 
     raster.setPixel(pix, cx - y, cy); 
    } else 
    if (x == y) { 
     raster.setPixel(act, cx + x, cy + y); 
     raster.setPixel(pix, cx - x, cy + y); 
     raster.setPixel(pix, cx + x, cy - y); 
     raster.setPixel(pix, cx - x, cy - y); 
    } else 
    if (x < y) { 
     raster.setPixel(act, cx + x, cy + y); 
     raster.setPixel(pix, cx - x, cy + y); 
     raster.setPixel(pix, cx + x, cy - y); 
     raster.setPixel(pix, cx - x, cy - y); 
     raster.setPixel(pix, cx + y, cy + x); 
     raster.setPixel(pix, cx - y, cy + x); 
     raster.setPixel(pix, cx + y, cy - x); 
     raster.setPixel(pix, cx - y, cy - x); 
    } 
}