在装配中绘制完美填充的圆(圆盘)的最简单方法是什么?

What is the easiest way to draw a perfectly filled circle(disc) in assembly?

我想在 320x200 模式下以 100 像素半径在组件中绘制一个完美填充的*圆(圆盘)。 quickest/easiest 方法是什么?

(*:我的意思是,当光盘的颜色为常亮白色且其中没有黑色像素时,光盘就完美填充了。)

如果您所说的最快是指最快的编写速度,这里有一个简单的 DOS 解决方案。

除了退出服务外,它不使用任何 DOS 服务。
它旨在生成一个 COM 文件(带有 NASM 的原始输出很好,只需将其重命名为 COM 扩展名即可)。

BITS 16

ORG 100h

push 0a000h           ;Video memory graphics segment
pop es

mov ax, 0013h         ;320x200@8bpp
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

只是给定一些参数写平面图形的一种常用技术,称为光栅化。

给定圆心 C(x, y) 和半径 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 

其中每个数字可能是一位或一个字节,具体取决于您的速度与内存限制。
然后您可以将此块直接复制到视频内存中或将其用作模板(一种色度键技术)。
要打印圆的其他四分之三,请简单地玩计数器。

如果半径不固定你可以通过

提升上面的代码
  • 内联函数调用
  • 尽量避免使用栈
  • 不要在每个周期都计算距离,而是使用基本微积分根据先前的值计算距离。
  • 一次计算超过一个像素并组合文字。

找到关于如何画圆的这篇文章。抱歉,未满。在这里阅读整篇文章: 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);
    }
}