我希望在320x200模式下以100像素半径在装配中绘制完美填充的*圆(圆盘)。什么是最快捷/最简单的方式?
(*:我的意思是当光盘的颜色为常白并且没有黑色像素时,光盘会被完美填充。)
答案 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);
}
}