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

时间:2015-07-22 12:36:26

标签: assembly nasm tasm

我希望在320x200模式下以100像素半径在装配中绘制完美填充的*圆(圆盘)。什么是最快捷/最简单的方式?

(*:我的意思是当光盘的颜色为常白并且没有黑色像素时,光盘会被完美填充。)

2 个答案:

答案 0 :(得分:2)

如果最快,你的意思是最快的写,这里是一个简单的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 

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

如果半径不固定,您可以通过

增强上面的代码
  • 内联函数调用
  • 尽可能避免使用堆栈
  • 不要计算每个周期的距离,而是使用基本微积分从之前的值计算它。
  • 一次计算多个像素并合并文字。

答案 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);
    }
}