kreis darstellen?



  • ich hab in nem tut hinweise drauf bekommen wie man kreise in (t)asm darstellt.
    das problem: es waren halt nur tips, aber kein source!!
    wie mach ich das nu???

    danke im voraus!



  • hi,
    hier ist ein beispiel. die prozedur ist eigentlich viel zu langsam, da sie die wurzelfunktion benutzt, wegen:
    r²=x²+y²
    und somit:
    y=wurzel(r²-x²)

    aber zum kreise zeichnen eignet sich ´schon ganz gut. naja, ein kleiner speedup ist, dass sie nur ein achtel des kreises ausrechnet und dann spiegelt, weil man in einem kreis alle achtel auf einander spiegeln kann.
    weiter unten ist nochmal c++ code der macht dasselbe, dachte nur, dass du es dann vielleicht einfacher hättest durch den code zu steigen.

    model tiny, pascal
    locals
    
    .code
            org     100h
    main:
    .386
            fstenv  [ENV]
            mov     ax,13h
            int     10h
    
            mov     cx,99
    repeat:
            CALL    circle,160,100,cx,cx
            dec     cx
            jnz     repeat
    
            mov     ah,08h
            int     21h
    
            mov     ax,03h
            int     10h
            fldenv  [ENV]
    
            ret
    .8086
    public circle
    circle proc near USES ax bx dx es,X0,Y0,R : word,COL0 : byte
       local X,Y,Rq : word
    
            mov     ax,0A000h
            mov     es,ax
            mov     dl,byte ptr [COL0]
    
            mov     [X],0
    
            ffree   st(7)
            fild    [R]
            fmul    st(0),st(0)     ;r² berechnen
            fist    [Rq]            ; und in Rq speichern
    
    @@calc_oct:
            ffree   st(6)
            ffree   st(7)
            fild    [X]             ;
            fmul    st(0),st(0)     ; x² berechnen
            fild    [Rq]            ; r²-x²
            fsub    st(0),st(1)
            fsqrt                   ; daraus die wurzel
            fist    [Y]             ; in y speichern also y = wurzel(r²-x²)
    
            CALL    circ_pix,[X],[Y],[X0],[Y0]    ; den pixel setzen bei x,y
            CALL    circ_pix,[Y],[X],[X0],[Y0]    ; bei y,x
            neg     [X]                           ; jetzt spiegeln
            CALL    circ_pix,[X],[Y],[X0],[Y0]    ; bei -x,y setzen
            CALL    circ_pix,[Y],[X],[X0],[Y0]    ; y,-x
            neg     [Y]
            CALL    circ_pix,[X],[Y],[X0],[Y0]    ; -x,-y
            CALL    circ_pix,[Y],[X],[X0],[Y0]    ; ....
            neg     [X]
            CALL    circ_pix,[X],[Y],[X0],[Y0]    ; ..... ... ...
            CALL    circ_pix,[Y],[X],[X0],[Y0]
            neg     [Y]
    
            inc     [X]
            mov     ax,[X]
            cmp     ax,[Y]                ; schleife für x
            jnl     @@finished    ; wenn x>=y dann sind wir mit dem achtel fertig
            jmp     @@calc_oct            
    @@finished:
    
            ret
    ; ------ das hier soll ne lokale prozedur sein, ist glaub ich nicht ganz lokal
    ; sie setzt nen pixel bei (Xc+Xt,Yc+Yt) ... (Xt/Yt) ist der mittelpunkt des 
    ; kreises
    
    circ_pix proc near Xc,Yc,Xt,Yt
            mov     ax,[Yc]
            add     ax,[Yt]
            mov     bx,[Xc]
            add     bx,[Xt]
    
            xchg    ah,al
            add     bx,ax
    .286
            shr     ax,2
    .8086
            add     bx,ax
            mov     es:[bx],dl
    
            ret
    circ_pix endp
    
    circle endp
    
    ENV dw 7 dup (?)
    
    end     main
    

    ----------------------------------------------------------------------
    dasselbe nun in C++
    ----------------------------------------------------------------------

    #include <dos.h>
    #include <math.h>
    #include <conio.h>
    #include <stdlib.h>
    
    unsigned char far* vga = (unsigned char far*)0xA0000000;
    int x,y,r;
    unsigned int i;
    unsigned char col;
    
    void circle(int x0,int y0,int r,int col)
    {
       int x,y,rq = r*r;     // hier auch r² berechnen und in rq speichern
    
           for (x = 0; x < y ; x++)
          {
            y = sqrt(rq-x*x);      // dasselbe wie oben
                 // pixel setzen und den achtel spiegeln 
            vga[(x+x0)+((y+y0) << 8)+((y+y0) << 6)] = col;
            vga[(x+x0)+((-y+y0) << 8)+((-y+y0) << 6)] = col;
            vga[(y+x0)+((x+y0) << 8)+((x+y0) << 6)] = col;
            vga[(y+x0)+((-x+y0) << 8)+((-x+y0) << 6)] = col;
            vga[(-x+x0)+((y+y0) << 8)+((y+y0) << 6)] = col;
            vga[(-x+x0)+((-y+y0) << 8)+((-y+y0) << 6)] = col;
            vga[(-y+x0)+((x+y0) << 8)+((x+y0) << 6)] = col;
            vga[(-y+x0)+((-x+y0) << 8)+((-x+y0) << 6)] = col;
          }
    
    }
    
    main()
    {
        asm {
             mov ax,13h
             int 10h
            }
    
    do {
            x = random(320);
            y = random(200);
            r = random(100);
            col = random(256);
            circle(x,y,r,col);
    
          } while (inportb(0x60) != 1);
    
        asm {
             mov ax,03h
             int 10h
            }
    
    }
    


  • ach ja, wollte noch sagen dass du dich mit bresenham algorithmen beschäftigen solltest wenn du schnelle kreisroutinen willst. aber naja, auf den heutigen rechnern merkt das auge nix.



  • hab grad gemerkt dass ich noch eine version mit ein paar verbesserungen hab, sorry möchte den thread eigentlich ncith vollspammen:

    model tiny,pascal
    locals
    
    .code
            org     100h
    main:
    .386
            fstenv  [ENV]
            mov     ax,13h
            int     10h
    
            mov     cx,99
    repeat:
            CALL    circle,160,100,cx,cx
            dec     cx
            jnz     repeat
    
            mov     ah,08h
            int     21h
    
            mov     ax,03h
            int     10h
            fldenv  [ENV]
    
            ret
    .8086
    public circle
    circle proc near USES ax bx dx es,X0,Y0,R : word,COL0 : byte
       local X,Y : word
       local Rq : dword
    
            mov     ax,0A000h
            mov     es,ax
            mov     dl,byte ptr [COL0]
    
            mov     [X],0
    
            ffree   st(7)
            fild    [R]
            fmul    st(0),st(0)
            fstp    dword ptr [Rq]
    
    @@calc_oct:
            ffree   st(6)
            fild    [X]
            fmul    st(0),st(0)
            fld     [Rq]
            fsub    st(0),st(1)
            fsqrt
            fistp   [Y]
    
            CALL    circ_pix,[X],[Y],[X0],[Y0]
            CALL    circ_pix,[Y],[X],[X0],[Y0]
            neg     [X]
            CALL    circ_pix,[X],[Y],[X0],[Y0]
            CALL    circ_pix,[Y],[X],[X0],[Y0]
            neg     [Y]
            CALL    circ_pix,[X],[Y],[X0],[Y0]
            CALL    circ_pix,[Y],[X],[X0],[Y0]
            neg     [X]
            CALL    circ_pix,[X],[Y],[X0],[Y0]
            CALL    circ_pix,[Y],[X],[X0],[Y0]
            neg     [Y]
    
            inc     [X]
            mov     ax,[X]
            cmp     ax,[Y]
            jnl     @@finished
            jmp     @@calc_oct
    @@finished:
    
            ret
    
    circ_pix proc near Xc,Yc,Xt,Yt
            mov     ax,[Yc]
            add     ax,[Yt]
            mov     bx,[Xc]
            add     bx,[Xt]
    
            xchg    ah,al
            add     bx,ax
    .286
            shr     ax,2
    .8086
            add     bx,ax
            mov     es:[bx],dl
    
            ret
    circ_pix endp
    
    circle endp
    
    ENV dw 7 dup (?)
    
    end     main
    


  • obiges C++-Programm ist nicht portabel (random, inportb). 🙄


Anmelden zum Antworten