BASIC

Author Topic: 2Ddrawellipse()  (Read 1433 times)

Offline sf-in-sf

  • Mr. Drawsprite
  • **
  • Posts: 93
  • Artist F.P. Brixey
    • View Profile
    • My computed art project
2Ddrawellipse()
« on: 2013-Mar-23 »
Read, use, enjoy! (I haven't tried your version yet, Gernot, you've been quicker than me.)
I'm surprised that the plotting with alpha seems to take much longer than the calculations and area scanning.
Any idea to improve that?

Code: GLBasic [Select]
// --------------------------------- //
// Project: ellipse1
// Start: Saturday, March 16, 2013
// IDE Version: 10.244


// SETCURRENTDIR("Media") // go to media files
// --------------------------------- //
// Project: circle1
// Start: Sunday, February 03, 2013
// IDE Version: 10.244


// SETCURRENTDIR("Media") // go to media files
GLOBAL scrx%=666, scry%=666 //your custom size.
// For PC use menu;project;options;
GETSCREENSIZE scrx, scry
SETSCREEN scrx,scry,0           // Size matters.
CREATESCREEN 1,1,scrx,scry
        // the drawing surface.
GLOBAL cnt%
CONSTANT framing=0.12 // i.e. 12%
//****************************************************
WHILE TRUE
        //press F12 to view long lines of code.
        LOCAL alpha=(RND(1999)/1000.0 -1.0)+0.00000003
                // additive when >0
                // interpolated when <0, ='mix' ='cross-fade'
                // ...in my opinion.
        LOCAL color%=RGB(128*RND(2)-1,128*RND(2)-1,128*RND(2)-1)
        LOCAL smoothedge = 2.2 +13*RND(3)
        LOCAL thickness=3*RND(9) // (0 means filled ellipse, in 2nd Fn).
//      USESCREEN 1

//define the x,y of the 2 centers:
GLOBAL c1x%=scrx*framing+RND(scrx*(1-framing-framing))
GLOBAL c2x%=scrx*framing+RND(scrx*(1-framing-framing))
GLOBAL c1y%=scry*framing+RND(scry*(1-framing-framing))
GLOBAL c2y%=scry*framing+RND(scry*(1-framing-framing))
GLOBAL rr_=SQR((c1x-c2x)*(c1x-c2x)+(c1y-c2y)*(c1y-c2y))*(1.03+RND(800)*0.001)
// rr_ is the length of the string stretched between the 2 centers.
// As you draw, keep the string tentioned with the pen.
// Try at home with 2 pins on a piece of cardboard.

IF TRUE //RND(1) >0
// Choose which Fn:
//      drawellipse1(c1x,c1y,c2x,c2y,SQR((c1x-c2x)*(c1x-c2x)+(c1y-c2y)*(c1y-c2y))*(1.03+RND(800)*0.001),color, alpha)//, smoothedge)
        drawellipse2(c1x,c1y,c2x,c2y,rr_, thickness,color, alpha, smoothedge)
ENDIF

        //USEASBMP // optional
        USESCREEN -1
        ALPHAMODE -1
        DRAWSPRITE 1,0,0
        SHOWSCREEN
                INC cnt,1
                IF cnt >4
                        cnt=0
                        SEEDRND (GETTIMERALL()) //shuffle the cards.
                ENDIF

//FOR more clarity:
        //DEBUG alpha ; DEBUG "\n"
        // please activate the 'bug' icon
//      SLEEP 2012 // additional time

        SLEEP 999
WEND
//****************************************************



// On the day the atom is a cube I will believe in the square pixel.


//__________________________________________________________________________________

FUNCTION drawellipse1:c1x%,c1y%,c2x%,c2y%,r%,col%,a //raw, filled shape, fast Fn no smoothing.

LOCAL r2% = r*r //?
LOCAL bx1%,bx2%,by1%,by2%
IF r <SQR((c1x-c2x)*(c1x-c2x)+(c1y-c2y)*(c1y-c2y)) THEN RETURN 0
        //impossible to draw, string is too short.
USESCREEN 1

IF c1x >=c2x
        bx2 = c2x +r //(approx.)
        bx1 = c1x -r
ELSE
        bx2 = c1x +r
        bx1 = c2x -r
ENDIF
IF c1y >=c2y
        by2 = c2y +r
        by1 = c1y -r
ELSE
        by2 = c1y +r
        by1 = c2y -r
ENDIF
ALPHAMODE a
FOR x%=bx1 TO bx2
FOR y%=by1 TO by2

        IF SQR((x-c1x)*(x-c1x) +(y-c1y)*(y-c1y)) +SQR((x-c2x)*(x-c2x) +(y-c2y)*(y-c2y)) <= r THEN SETPIXEL x,y,col
NEXT
NEXT
RETURN 1
ENDFUNCTION


FUNCTION drawellipse2:c1x%,c1y%,c2x%,c2y%,r,thick,col%,a,smoo //raw shape

IF r <SQR((c1x-c2x)*(c1x-c2x)+(c1y-c2y)*(c1y-c2y)) THEN RETURN 0
        //impossible to draw, string is too short.

IF smoo <0 THEN smoo =0
smoo=smoo*1.8 // approx.correction
LOCAL halfsmoo =smoo*0.5
LOCAL th =thick*0.5
LOCAL smoooo =smoo+smoo
LOCAL rs1 =r+smoooo
LOCAL ra  = (r+halfsmoo+th)
LOCAL rb  = (r+th)                                      //
LOCAL rc  = (r-th)                                      //
LOCAL rd  = (r-th-halfsmoo)

LOCAL d,d2
LOCAL r2 =r*r
LOCAL w_out =ra-(r+th) +0.000001//r2_ -r2
LOCAL w_in  =(r-th)-rd +0.000001
LOCAL w_out_plain =rs1-(r) +0.000001
LOCAL bx1%,by1%,bx2%,by2%
USESCREEN 1


IF c1x >=c2x
        bx2 = c2x +r +th +smoooo //(approx.)
        bx1 = c1x -r -th -smoooo
ELSE
        bx2 = c1x +r +th+smoooo
        bx1 = c2x -r -th-smoooo
ENDIF
IF c1y >=c2y
        by2 = c2y +r +th+smoooo//(approx.)
        by1 = c1y -r -th-smoooo
ELSE
        by2 = c1y +r +th+smoooo
        by1 = c2y -r -th-smoooo
ENDIF

FOR x%=bx1 TO bx2
FOR y%=by1 TO by2
//FOR x%=0 TO scrx
//FOR y%=0 TO scry
LOCAL d=SQR((x-c1x)*(x-c1x) +(y-c1y)*(y-c1y)) +SQR((x-c2x)*(x-c2x) +(y-c2y)*(y-c2y))
IF thick=0 // elliptic disc
        IF d <= r
                ALPHAMODE a
                SETPIXEL x,y,col //print it plain
        ELSEIF d <= rs1 // then interpolate the alpha.
                ALPHAMODE (rs1-d)*a/smoooo
                SETPIXEL x,y,col

        ENDIF
ELSE // outlined ellipse
        IF d <= r //internal

                IF d >= rc
                        //plot it plain.
                        ALPHAMODE a
                        SETPIXEL x,y,col
                ELSEIF d <=  rd
                        // ignore it
                ELSE
                        // interpolate, blend it.
                        ALPHAMODE (d -rd)*a/w_in
                        SETPIXEL x,y,col
                ENDIF
        ELSE //external

                IF d < rb
                        //plot it plain.
                        ALPHAMODE a
                        SETPIXEL x,y,col
                ELSEIF d >=  ra
                        // ignore it
                ELSE
                        // interpolate, blend it.
                        ALPHAMODE (ra -d)*a/w_out
                        SETPIXEL x,y,col
                ENDIF
        ENDIF
ENDIF

NEXT
NEXT
RETURN 1 // Smooth operation hopefully
ENDFUNCTION

// P.S. On the day the atom is a cube I will believe in the square pixel.
 
On the day the atom is a cube I will start believing in the square pixel.

Offline bigsofty

  • Community Developer
  • Prof. Inline
  • ******
  • Posts: 2510
    • View Profile
Re: 2Ddrawellipse()
« Reply #1 on: 2013-Mar-25 »
Very nice!  :good:

In OpenGL in general switching the drawing state too regularly is to be avoided as its a slow operation. So if you could move ALPHAMODE outside of your loops, it may be quicker. Also, I have found that doing some OpenGL inline can be a bit quicker too as you have more control over the low level drawing operations. As mentioned by Fuzzy70, MEM2SPRITE can also be a good way to draw lots of pixels fast.
Cheers,

Ian.

“It is practically impossible to teach good programming style to students that have had prior exposure to BASIC.  As potential programmers, they are mentally mutilated beyond hope of regeneration.”
(E. W. Dijkstra)