April 29, 2024, 02:16:03 PM

News:

Own IWBasic 2.x ? -----> Get your free upgrade to 3.x now.........


2D Bezier Curve Example by Rich

Started by pistol350, September 04, 2007, 10:49:35 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

pistol350


'2D Bezier Curve Example
'by Rich Schafermeyer
def win:window
def x0,y0,bezdotnum,bezsegnum,bxy[10]:int
def dotstate,dotnumber,winT,winL,winW,winH:int
def rdotnumber:int

'bezier curve: bezdotnum = number of dots that make curve (2-5), bezsegnum = number of straight lines that make up curve,
'bxy: array of x-y pairs that define control dot location in order from left [0] to right [9]
declare bezier(bezdotnum:int,bezsegnum:int,bxy[10]:int)

window win,0,0,800,600,@minbox|@maxbox|@size|@noautodraw,0,"2D Bezier Curve Example",main
centerwindow win
'make directx screen
if createscreen (win,800,600) < 0
    messagebox win, "Could not create DirectX screen","Error"
    closewindow win
    end
endif

run = 1

'set center
x0=500:y0=350

'initialize starting variables
bxy[0]=x0-200,y0,x0-150+rnd(200),y0-200+rnd(400),x0-100+rnd(200),y0-200+rnd(400),x0+50+rnd(200),y0-200+rnd(400),x0+200,y0
bezdotnum=4:bezsegnum=16
rdotnumber=1
'create controls
control win,"S,,20,160,101,16,0x50000000,1"
control win,"E,Edit1,130,159,70,20,0x50800800,2"
control win,"R,3 Dot Bezier,20,51,120,20,0x50000009,3"
control win,"R,4 Dot Bezier,20,74,120,20,0x50000009,4"
control win,"R,5 Dot Bezier,20,97,120,20,0x50000009,5"
setcontrolcolor win,3,0,rgb(255,255,255)
setcontrolcolor win,4,0,rgb(255,255,255)
setcontrolcolor win,5,0,rgb(255,255,255)
setcontroltext win,2,str$(bezsegnum)
setscrollrange win,1,1,32
setscrollpos win,1,bezsegnum
setstate win,4,1

gosub makerandomline

waituntil run =0
closewindow win
end

sub main
 
select @class
   case @idrbuttondn
        bxy[dotnumber -1]=@mousex:bxy[dotnumber+1]=@mousey
        gosub makeline
   case @iddxupdate
      dxflip win,0,0
   case @idrbuttondn
bxy[rdotnumber - 1]=@mousex:bxy[rdotnumber]=@mousey
       gosub makeline
case @idclosewindow
           run = 0
   'change number of bezier dots used
   case @IDCONTROL
      if @CONTROLID > 2
          bezdotnum=@controlid
         setfocus win
         gosub makeline
      endif
   'change number of line segments used
   case @IDHSCROLL
      select @CODE
         case @SBTHUMBPOS:case @SBTHUMBTRACK
            setscrollpos win,1,@QUAL
         case @SBLINELEFT
            setscrollpos win,1,(getscrollpos(win,1)-1)
         case @SBLINERIGHT
            setscrollpos win,1,(getscrollpos(win,1)+1)
         case @SBPAGELEFT
            setscrollpos win,1,(getscrollpos(win,1)-5)
         case @SBPAGERIGHT
            setscrollpos win,1,(getscrollpos(win,1)+5)
      endselect
      bezsegnum = getscrollpos(win,1)
      setcontroltext win,2,str$(bezsegnum)
      gosub makeline
   case @idchar
      gosub makerandomline
   case @idlbuttondn
      gosub checkfordot
   case @idlbuttonup
      dotnumber = 0
   case @idmousemove
      if dotnumber > 0
         bxy[dotnumber - 1]=@mousex:bxy[dotnumber]=@mousey
         gosub makeline
      endif
   'reposition line when window size is changed
   case @idsize
      getclientsize win,winL,winT,winW,winH
      x0=50+winW/2:y0=50+winH/2
      if bezdotnum > 0 then gosub makerandomline
endselect
return

'draw line without randomizing dots
sub makeline
dxfill win, rgb(255,255,255)

move win,20,15
print win,"Hit any key to randomize control dots or left-click on a dot and drag"
move win,20,135
print win,"Set Number of Line Segments in Bezier Curve:"
bezier(bezdotnum,bezsegnum,bxy)
return

'draw line after randomining dots
sub makerandomline
bxy[0]=x0-200,y0,x0-150+rnd(200),y0-200+rnd(400),x0-100+rnd(200),y0-200+rnd(400),x0+50+rnd(200),y0-200+rnd(400),x0+200,y0
gosub makeline
return

sub bezier(bezdotnum,bezsegnum,bxy)
def incr,i,i1,i2,i3,i4,x,y:float
def j:int
incr = 1/bezsegnum : i = 0
move win,bxy[0],bxy[1]
setlinestyle win,@lssolid,3
for j = 0 to bezsegnum
i1 = 1 - i : i2 = (1 - i) * i1 : i3 = (1 - i) * i2 : i4 = (1 - i) * i3
select bezdotnum
   case 2
      x=bxy[0]*i1+bxy[8]*i
      y=bxy[1]*i1+bxy[9]*i
   case 3
      x=bxy[0]*i2+bxy[4]*2*i*i1+bxy[8]*i*i
      y=bxy[1]*i2+bxy[5]*2*i*i1+bxy[9]*i*i
   case 4   
      x=bxy[0]*i3+bxy[2]*3*i*i2+bxy[6]*3*i*i*i1+bxy[8]*i^3
      y=bxy[1]*i3+bxy[3]*3*i*i2+bxy[7]*3*i*i*i1+bxy[9]*i^3
   case 5
      x=bxy[0]*i4+bxy[2]*4*i*i3+bxy[4]*6*i*i*i2
      x=x+bxy[6]*4*i^3*i1+bxy[8]*i^4
      y=bxy[1]*i4+bxy[3]*4*i*i3+bxy[5]*6*i*i*i2
      y=y+bxy[7]*4*i^3*i1+bxy[9]*i^4
endselect
line win,x,y
i = i + incr
next j
'draw squares at start and end of line, open circles at control points
rect win,bxy[0]-3,bxy[1]-3,6,6,rgb(255,0,0),rgb(255,0,0)
rect win,bxy[8]-3,bxy[9]-3,6,6,rgb(255,0,0),rgb(255,0,0)
select bezdotnum
   case 3
      circle win,bxy[4],bxy[5],3,rgb(255,0,0)
   case 4
      circle win,bxy[2],bxy[3],3,rgb(0,255,0)
      circle win,bxy[6],bxy[7],3,rgb(0,0,255)
   case 5
      circle win,bxy[2],bxy[3],3,rgb(0,255,0)
      circle win,bxy[4],bxy[5],3,rgb(255,0,0)
      circle win,bxy[6],bxy[7],3,rgb(0,0,255)
endselect
return

'check to see if mouse is over dot and left mouse button down;
'if so, drag dot to new location
sub checkfordot
def i:int
dotnumber = 0
for i=0 to 8 # 2
if (@mousex > (bxy[i]-4)) & (@mousex < (bxy[i]+4)) & (@mousey > (bxy[i+1]-4)) & (@mousey < (bxy[i+1]+4))
    rdotnumber = i + 1
    dotnumber = i + 1
endif
next i
return
Regards,

Peter B.