Рекурсивное рисование линии


Ранее видел этот заумный способ рисовании линии на сайте , занялся переделкой на разные языки
Purebasic
Procedure dra(x1.l,y1.l,x2.l,y2.l)
  midx.l=(x1+x2)/2
  midy.l=(y1+y2)/2
  If midx<>x1 And midy<>y1
    dra(midx,midy,x1,y1)
    dra(x2,y2,midx,midy)
    Box(midx,midy,1,1,$FFFFFF)
  EndIf
EndProcedure

If InitSprite() And OpenWindow(0,0,0,640,480,"Recursive draw",#PB_Window_SystemMenu) And OpenWindowedScreen(WindowID(0),0,0,640,480,0,0,0) 
  StartDrawing(ScreenOutput()) 
  dra(0,0,640,480)
        StopDrawing() 
        FlipBuffers() 
 Repeat 
  Until WindowEvent()=#PB_Event_CloseWindow 
EndIf

Z80(оригинал, sjasmplus)
;http://retro666.rssing.com/browser.php?indx=7149388&item=40
;While attempting to write a game in 256 bytes I needed a routine to draw lines, but Bresenham's line algorithm weighs in at approx ~120 bytes. The only suitable alternative I'm aware of is recursive divide and conquer: divide a line into two smaller lines and call the draw routine with each in turn:
;
;/* Draw a line from (ax,ay) to (bx,by) */
;
;int draw ( ax, ay, bx, by )
;{
;    int midx, midy;
;    midx = ( ax+bx ) / 2;
;    midy = ( ay+by ) / 2;
;    if ( midx != ax && midy != ay )
;    {
;        draw( midx, midy, ax, ay );
;        draw( bx, by, midx, midy );
;        plot( midx, midy );
;    }
;}
;This is significantly smaller thank Bresenham's, 32 byte of Z80. However, there are a couple of compromises: it's slower and the lines aren't perfect because the rounding errors accumulate.

device zxspectrum128
        ORG #6000
begin

ld hl,0,de,$FFBF
call DRAW
jr $
; draw lines using recursive divide and conquer
; from de = end1 (d = x-axis, e = y-axis)
; to   hl = end2 (h = x-axis, l = y-axis)

DRAW:
  call PLOT

  push hl

; calculate hl = centre pixel

  ld a,l
  add a,e
  rra
  ld l,a
  ld a,h
  add a,d
  rra
  ld h,a

; if de (end1) = hl (centre) then we're done

  or a
  sbc hl,de
  jr z,EXIT
  add hl,de

  ex de,hl
  call DRAW    ; de = centre, hl = end1
  ex (sp),hl
  ex de,hl
  call DRAW    ; de = end2, hl = centre

  ex de,hl
  pop de
  ret

EXIT:
  pop hl
  ret

; ---------------------------

; plot d = x-axis, e = y-axis

PLOT:
  push hl
  ld a,d
  and 7
  ld b,a
  inc b
  ld a,e
  rra
  scf
  rra
  or a
  rra
  ld l,a
  xor e
  and 248
  xor e
  ld h,a
  ld a,l
  xor d
  and 7
  xor d
  rrca
  rrca
  rrca
  ld l,a
  ld a,1
PLOTBIT:
  rrca
  djnz PLOTBIT
  or (hl)
  ld (hl),a
  pop hl
  ret
end
display /d,end-begin
savesna "!void.sna",begin


x86(Flat assembler), 98bytes
org 100h
use16

mov al,13h
int 10h
xor cx,cx
xor dx,dx
mov bp,319
mov di,199
call drw
ret
;/* Draw a line from (ax,ay) to (bx,by) */
;int draw ( ax, ay, bx, by )
drw: ; ax=CX,ay=DX,bx=BP,by=DI
;{
;    int midx, midy;
;    midx = ( ax+bx ) / 2;
mov ax,cx
add ax,bp
shr ax,1
;    midy = ( ay+by ) / 2;
mov si,di
add si,dx
shr si,1
;    if ( midx != ax && midy != ay )
cmp ax,cx
je eif
cmp si,dx
je eif
;    {
;        draw( midx, midy, ax, ay );
push ax
push cx
push dx
push bp
push di
push si
mov bp,cx
mov di,dx
mov cx,ax
mov dx,si
call drw
pop si
pop di
pop bp
pop dx
pop cx
pop ax
;        draw( bx, by, midx, midy );
push ax
push cx
push dx
push bp
push di
push si
mov cx,bp
mov dx,di
mov bp,ax
mov di,si
call drw
pop si
pop di
pop bp
pop dx
pop cx
pop ax
pusha
;        plot( midx, midy );
mov cx,ax
mov dx,si
xor bh,bh
mov ax,0C0Fh
int 10h
popa
;    }
eif:
ret

;INT 10h,  0Ch (12)       Write Pixel

;    Writes a pixel dot of a specified color at a specified screen
;    coordinate.

;       On entry:      AH         0Ch
;                      AL         Pixel color
;                      CX         Horizontal position of pixel
;                      DX         Vertical position of pixel
;                      BH         Display page number (graphics modes with more
;                                 than 1 page)

;       Returns:       None

;       Registers destroyed:      AX, SP, BP, SI, DI


Только качество хромает. Попробую разобраться. Исходники тут

Комментарии