It is currently Thu Dec 13, 2018 7:18 pm

All times are UTC + 1 hour




Post new topic Reply to topic  [ 8 posts ] 
Author Message
 Post subject: Math and vector graphics
PostPosted: Sat Nov 10, 2018 8:49 am 
Offline
Addict
Addict
User avatar

Joined: Thu Feb 09, 2006 11:27 pm
Posts: 2354
Would need some help again, I'd like to do rounded rectangles with light and shadow effect which works fine under simple conditions. But when using narrow boxes, everything gets scrambled... (I also want to implement a drop shadow which is even more complicate)

Here's an example which uses extra a large radius and wide light/shadow stripes to demonstrate the issues. Anyone good in math do create an universally working solution?

Code:
Procedure Min(a,b)
   If a<b
      ProcedureReturn a
   Else
      ProcedureReturn b
   EndIf
EndProcedure

Procedure AddPathRoundBox(x.d,y.d,w.d,h.d,radius.d,flags=#PB_Path_Default)

   If radius>h/2 : radius=h/2 : EndIf
   If radius>w/2 : radius=w/2 : EndIf

   If radius<0
      radius=0
   EndIf

   MovePathCursor(x+radius,y,flags)

   AddPathArc(w-radius,0,w-radius,radius,radius,#PB_Path_Relative)
   AddPathArc(0,h-radius,-radius,h-radius,radius,#PB_Path_Relative)
   AddPathArc(-w+radius,0,-w+radius,-radius,radius,#PB_Path_Relative)
   AddPathArc(0,-h+radius,radius,-h+radius,radius,#PB_Path_Relative)

   ClosePath()

   MovePathCursor(-radius,0,#PB_Path_Relative)

EndProcedure
Procedure AddPathHighlight(x.d,y.d,w.d,h.d,r.d,angle.d,flags=#PB_Path_Default)

   Protected t1.d,t2.d,t3.d,t4.d,t5.d

   t1=Cos(angle*#PI/180);   1-89°
   t2=Sin(angle*#PI/180)
   t3=r*t1
   t4=r*t2
   t5=2*r-t4

   MovePathCursor(x,y+r,flags)
   AddPathCircle(r,0,r,180,270,#PB_Path_Relative)
   AddPathLine(w-r*2,0,#PB_Path_Relative)
   AddPathCircle(0,r,r,270,270+angle,#PB_Path_Relative|#PB_Path_Connected)
   AddPathLine(-w+t5,0,#PB_Path_Relative)
   AddPathCircle(0,t3,t3,270,180,#PB_Path_Relative|#PB_Path_Connected|#PB_Path_CounterClockwise)
   AddPathLine(0,h-t5,#PB_Path_Relative)
   AddPathCircle(t3,-t4,r,180-angle,180,#PB_Path_Relative|#PB_Path_Connected)

   ClosePath()

EndProcedure
Procedure AddPathShadow(x.d,y.d,w.d,h.d,r.d,angle.d,flags=#PB_Path_Default)

   Protected ro.d
   Protected t1.d,t2.d,t3.d,t4.d,t5.d

   ro=Min(Min(r,h/2),w/2)

   t1=Cos(angle*#PI/180);   1-89°
   t2=Sin(angle*#PI/180)
   t3=r*t1
   t4=r*t2
   t5=2*r-t4

   r=ro
   Debug ro

   MovePathCursor(x+w,y+h-r,flags)
   AddPathCircle(-r,0,r,0,90,#PB_Path_Relative)
   AddPathLine(-w+r*2,0,#PB_Path_Relative)
   AddPathCircle(0,-r,r,90,90+angle,#PB_Path_Relative|#PB_Path_Connected)
   AddPathLine(w-t5,0,#PB_Path_Relative)
   AddPathCircle(0,-t3,t3,90,0,#PB_Path_Relative|#PB_Path_Connected|#PB_Path_CounterClockwise)
   AddPathLine(0,-h+t5,#PB_Path_Relative)
   AddPathCircle(-t3,t4,r,360-angle,360,#PB_Path_Relative|#PB_Path_Connected)

   ClosePath()

EndProcedure

Procedure boxs(x,y,w,h,radius,col,extra=8)


   AddPathRoundBox(x,y,w,h,radius)
   VectorSourceColor($a0000000|col)
   FillPath(#PB_Path_Preserve)
   VectorSourceColor($60000000)
   StrokePath(1)

   VectorSourceColor($40ffffff)
   AddPathHighlight(x,y,w,h,radius,extra*2)
   FillPath()
   AddPathHighlight(x,y,w,h,radius,extra*3)
   FillPath()
   VectorSourceColor($20000000)
   AddPathShadow(x,y,w,h,radius,extra*2)
   FillPath()
   AddPathShadow(x,y,w,h,radius,extra*3)
   FillPath()


   ; Debug "Data.i "+Str(boxnr)+", "+Str(x)+","+Str(y)+", "+Str(w)+","+Str(h)+"; "+Str(size)

EndProcedure
Procedure show()

   Protected i

   StartVectorDrawing(CanvasVectorOutput(0))
   AddPathBox(0,0,VectorOutputWidth(),VectorOutputHeight())
   VectorSourceColor($Ff000000|#White)
   FillPath()

   boxs(50,50,300,200,90,$F3D1AD)
   boxs(50,350,300,100,40,$F3D1AD,20);      smaller radius
   boxs(400,100,300,100,90,$9AF0B8)
   boxs(500,250,100,300,90,$9AF0B8,20)

   StopVectorDrawing()

EndProcedure

Procedure main()

   #X=800
   #Y=600

   OpenWindow(0,0,0,#X,#Y,"")
   CanvasGadget(0,0,0,#X,#Y)

   show()

   Repeat
      Select WaitWindowEvent()
      Case #PB_Event_CloseWindow
         End
      Case #WM_CHAR
         End
      EndSelect
   ForEver

EndProcedure
main()


Top
 Profile  
Reply with quote  
 Post subject: Re: Math and vector graphics
PostPosted: Sat Nov 10, 2018 11:38 am 
Offline
User
User

Joined: Thu Jul 09, 2015 9:07 am
Posts: 36
Hi,

my brush functions can also be used with a vectordrawing path
Doesn't that suit you?
https://www.purebasic.fr/french/viewtopic.php?f=6&t=16385


Top
 Profile  
Reply with quote  
 Post subject: Re: Math and vector graphics
PostPosted: Sat Nov 10, 2018 12:57 pm 
Offline
Addict
Addict
User avatar

Joined: Thu Feb 09, 2006 11:27 pm
Posts: 2354
I like your routines, but I believe the functions are only producing perfect results when drawing an opaque layer at the top. Give me a hint if this is correct (I only made a quick test replacing all occurrences of $FF by $80...

I need transparent shapes, maybe the following example makes this a little bit clearer:
Code:
Procedure Min(a,b)
   If a<b
      ProcedureReturn a
   Else
      ProcedureReturn b
   EndIf
EndProcedure

Procedure AddPathRoundBox(x.d,y.d,w.d,h.d,radius.d,flags=#PB_Path_Default)

   If radius>h/2 : radius=h/2 : EndIf
   If radius>w/2 : radius=w/2 : EndIf

   If radius<0
      radius=0
   EndIf

   MovePathCursor(x+radius,y,flags)

   AddPathArc(w-radius,0,w-radius,radius,radius,#PB_Path_Relative)
   AddPathArc(0,h-radius,-radius,h-radius,radius,#PB_Path_Relative)
   AddPathArc(-w+radius,0,-w+radius,-radius,radius,#PB_Path_Relative)
   AddPathArc(0,-h+radius,radius,-h+radius,radius,#PB_Path_Relative)

   ClosePath()

   MovePathCursor(-radius,0,#PB_Path_Relative)

EndProcedure
Procedure AddPathHighlight(x.d,y.d,w.d,h.d,r.d,angle.d,flags=#PB_Path_Default)

   Protected t1.d,t2.d,t3.d,t4.d,t5.d

   t1=Cos(angle*#PI/180);   1-89°
   t2=Sin(angle*#PI/180)
   t3=r*t1
   t4=r*t2
   t5=2*r-t4

   MovePathCursor(x,y+r,flags)
   AddPathCircle(r,0,r,180,270,#PB_Path_Relative)
   AddPathLine(w-r*2,0,#PB_Path_Relative)
   AddPathCircle(0,r,r,270,270+angle,#PB_Path_Relative|#PB_Path_Connected)
   AddPathLine(-w+t5,0,#PB_Path_Relative)
   AddPathCircle(0,t3,t3,270,180,#PB_Path_Relative|#PB_Path_Connected|#PB_Path_CounterClockwise)
   AddPathLine(0,h-t5,#PB_Path_Relative)
   AddPathCircle(t3,-t4,r,180-angle,180,#PB_Path_Relative|#PB_Path_Connected)

   ClosePath()

EndProcedure
Procedure AddPathShadow(x.d,y.d,w.d,h.d,r.d,angle.d,flags=#PB_Path_Default)

   Protected ro.d
   Protected t1.d,t2.d,t3.d,t4.d,t5.d

   ro=Min(Min(r,h/2),w/2)

   t1=Cos(angle*#PI/180);   1-89°
   t2=Sin(angle*#PI/180)
   t3=r*t1
   t4=r*t2
   t5=2*r-t4

   r=ro
   Debug ro

   MovePathCursor(x+w,y+h-r,flags)
   AddPathCircle(-r,0,r,0,90,#PB_Path_Relative)
   AddPathLine(-w+r*2,0,#PB_Path_Relative)
   AddPathCircle(0,-r,r,90,90+angle,#PB_Path_Relative|#PB_Path_Connected)
   AddPathLine(w-t5,0,#PB_Path_Relative)
   AddPathCircle(0,-t3,t3,90,0,#PB_Path_Relative|#PB_Path_Connected|#PB_Path_CounterClockwise)
   AddPathLine(0,-h+t5,#PB_Path_Relative)
   AddPathCircle(-t3,t4,r,360-angle,360,#PB_Path_Relative|#PB_Path_Connected)

   ClosePath()

EndProcedure

Procedure boxs(x,y,w,h,radius,col,extra=8)


   AddPathRoundBox(x,y,w,h,radius)
   VectorSourceColor($a0000000|col)
   FillPath(#PB_Path_Preserve)
   VectorSourceColor($60000000)
   StrokePath(1)

   VectorSourceColor($40ffffff)
   AddPathHighlight(x,y,w,h,radius,extra*2)
   FillPath()
   AddPathHighlight(x,y,w,h,radius,extra*3)
   FillPath()
   VectorSourceColor($20000000)
   AddPathShadow(x,y,w,h,radius,extra*2)
   FillPath()
   AddPathShadow(x,y,w,h,radius,extra*3)
   FillPath()


   ; Debug "Data.i "+Str(boxnr)+", "+Str(x)+","+Str(y)+", "+Str(w)+","+Str(h)+"; "+Str(size)

EndProcedure
Procedure show()

   Protected i

   StartVectorDrawing(CanvasVectorOutput(0))
   AddPathBox(0,0,VectorOutputWidth(),VectorOutputHeight())
   VectorSourceColor($Ff000000|#White)
   FillPath()
   
   AddPathBox(100,150,450,250)
   VectorSourceColor($400000f0)
   FillPath()
   
   boxs(50,50,300,200,90,$F3D1AD)
   boxs(50,350,300,100,40,$F3D1AD,20);      smaller radius
   boxs(400,100,300,100,90,$9AF0B8)
   boxs(500,250,100,300,90,$9AF0B8,20)

   StopVectorDrawing()

EndProcedure

Procedure main()

   #X=800
   #Y=600

   OpenWindow(0,0,0,#X,#Y,"")
   CanvasGadget(0,0,0,#X,#Y)

   show()

   Repeat
      Select WaitWindowEvent()
      Case #PB_Event_CloseWindow
         End
      Case #WM_CHAR
         End
      EndSelect
   ForEver

EndProcedure
main()


And that's what I am able to produce with your code:
Code:
Macro doevents
   Repeat:Until WaitWindowEvent() = #PB_Event_CloseWindow
EndMacro
Macro VFill(c,flag=#PB_Path_Default)
   VectorSourceColor($20000000|(c&$FFFFFF))
   FillPath(flag)
EndMacro
Macro vcolor(c)
   VectorSourceColor(c)
EndMacro

Procedure SortIdx(Array t.l(1),Array idx.l(1),deb=0, fin=-1) ;<= met dans le tableau idx() la position des element trié du tableau t()

   Protected min,i,j,v,idmin
   If fin=-1: fin=ArraySize(t()):EndIf
   Dim idx(fin)
   For i=deb To fin:idx(i)=i:Next
   For i=deb To fin
      min=$7fffffff
      For j=i To fin
         v=t(idx(j))
         If v<min:min=v:idmin=j:EndIf
      Next
      Swap idx(i),idx(idmin)
   Next
EndProcedure
Procedure initIF(image,centerX.w=-1,centerY.w=-1)
   ;image : numero de l'image
   ;centerx/y : definit le centre de l'image
   Structure IFsij
      i.b
      j.b
   EndStructure

   Protected i,j,n,di,dj
   Protected idx=ImageWidth (image)
   Protected idy=ImageHeight(image)
   Protected Dim IFdis.l(idx * idy-1)
   Global IFcenterx
   If centerX=-1:IFcenterx=idx/2:Else:IFcenterx=centerx:EndIf
   Global IFcenterY
   If centery=-1:IFcentery=idy/2:Else:IFcentery=centery:EndIf
   Global Dim IFidx.l(idx * idy-1)
   Global Dim IFbmp.l(idx-1,idy-1)
   Global Dim IFpos.IFsij(idx * idy-1)

   StartDrawing(ImageOutput(image))
   DrawingMode(#PB_2DDrawing_AllChannels)
   For j=0 To idy-1
      For i=0 To idx-1
         IFbmp(i,j)=Point(i,j)
         IFpos(n)\i=i:di=i-IFcenterx
         IFpos(n)\j=j:dj=j-IFcentery
         ;IFdis(n)=di*di+dj*dj
         IFdis(n)=Abs(di)+Abs(dj)
         n+1
      Next
   Next
   StopDrawing()
   sortidx(IFdis(),IFidx())
EndProcedure
Procedure FillPathBrush(image,centerX.w=-1,centerY.w=-1)
   initIF(image,centerX,centerY)
   Protected s.s=PathSegments()
   Protected n,nn=ArraySize(IFidx())
   ResetPath()
   For n=0 To nn
      With IFpos(IFidx(nn-n))
         If Alpha(IFbmp(\i,\j))
            MovePathCursor(\i-ifcenterX+1,\j-ifcentery+1)
            AddPathSegments(s,#PB_Path_Relative)
            Vfill(IFbmp(\i,\j))
         EndIf
      EndWith
   Next
EndProcedure

Procedure exemple()
   EnableExplicit
   Protected i,j,n, a.f,y, idx=800,idy=600
   For n=0 To 7
      CreateImage(10+n,16,16,32,#PB_Image_Transparent)
      StartVectorDrawing(ImageVectorOutput(10+n))
      Select n
      Case 0
         VectorSourceCircularGradient(8-3,8-3,10)
         VectorSourceGradientColor($ffffffff, 0.0)
         VectorSourceGradientColor($ffffaaaa, 0.4)
         VectorSourceGradientColor($ff886666, 1.0)
         VectorSourceGradientColor($00886666, 1.0)
         AddPathCircle(8,8,7):FillPath()
      EndSelect
      StopVectorDrawing()
   Next

   CreateImage(0,idx,idy,32,#White)

   StartVectorDrawing(ImageVectorOutput(0))
   AddPathBox(480,100,100,260)
   VectorSourceColor($6000ff00)
   FillPath()

   y=i*72+10
   MovePathCursor(0,30+y)
   ;DrawVectorImage(ImageID(10+i))
   AddPathBox(380,200,200,60)
   FillPathBrush(10+i)

   StopVectorDrawing()

   OpenWindow(0, 0, 0, idx, idy, "VectorDrawing-Brush", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
   ImageGadget(0, 0, 0, idx, idy,ImageID(0))
   doevents
EndProcedure

exemple()


Top
 Profile  
Reply with quote  
 Post subject: Re: Math and vector graphics
PostPosted: Sat Nov 10, 2018 1:54 pm 
Offline
Addict
Addict

Joined: Thu Aug 30, 2007 11:54 pm
Posts: 869
Location: right here
I played a bit with this.
Code:
Procedure show()
   [...]
   ; some random background
   For i=0 To 1000
     AddPathBox(Random(VectorOutputWidth())-50,Random(VectorOutputHeight())-50, 50+Random(50), 50+Random(50))
     VectorSourceColor(RGBA(Random(255),Random(255),Random(255),Random(20)))
     FillPath()
   Next
   [...]


Code:
Procedure boxs(x,y,w,h,radius,col,extra=8)
 
  Protected alpha.f = 20
  Protected size = 20
  Protected offset.f = 5
  Protected color = $60000000
 
  For i=1 To size
     AddPathRoundBox( (x-(offset*(i/size))), (y-(offset*(i/size))), (w+i), (h+i), ((w+i)*radius/w) )
     VectorSourceColor(RGBA(Red(color), Green(color), Blue(color), alpha*((size-i)/size)))
     StrokePath(1)
  Next

  [...]


I'm drawing the round-box outline multiple times with increasing size and decreasing alpha. I used an offset so the shadow is larger on the bottom-right than it is on the top-left. Unfortunately it becomes also denser/darker in the top-left, which looks counterintuitive. If you use an offset of size/2 it looks ok though. Maybe that's a start :)

Code:
Procedure Min(a,b)
   If a<b
      ProcedureReturn a
   Else
      ProcedureReturn b
   EndIf
EndProcedure

Procedure AddPathRoundBox(x.d,y.d,w.d,h.d,radius.d,flags=#PB_Path_Default)

   If radius>h/2 : radius=h/2 : EndIf
   If radius>w/2 : radius=w/2 : EndIf

   If radius<0
      radius=0
   EndIf

   MovePathCursor(x+radius,y,flags)

   AddPathArc(w-radius,0,w-radius,radius,radius,#PB_Path_Relative)
   AddPathArc(0,h-radius,-radius,h-radius,radius,#PB_Path_Relative)
   AddPathArc(-w+radius,0,-w+radius,-radius,radius,#PB_Path_Relative)
   AddPathArc(0,-h+radius,radius,-h+radius,radius,#PB_Path_Relative)

   ClosePath()

   MovePathCursor(-radius,0,#PB_Path_Relative)

EndProcedure
Procedure AddPathHighlight(x.d,y.d,w.d,h.d,r.d,angle.d,flags=#PB_Path_Default)

   Protected t1.d,t2.d,t3.d,t4.d,t5.d

   t1=Cos(angle*#PI/180);   1-89°
   t2=Sin(angle*#PI/180)
   t3=r*t1
   t4=r*t2
   t5=2*r-t4

   MovePathCursor(x,y+r,flags)
   AddPathCircle(r,0,r,180,270,#PB_Path_Relative)
   AddPathLine(w-r*2,0,#PB_Path_Relative)
   AddPathCircle(0,r,r,270,270+angle,#PB_Path_Relative|#PB_Path_Connected)
   AddPathLine(-w+t5,0,#PB_Path_Relative)
   AddPathCircle(0,t3,t3,270,180,#PB_Path_Relative|#PB_Path_Connected|#PB_Path_CounterClockwise)
   AddPathLine(0,h-t5,#PB_Path_Relative)
   AddPathCircle(t3,-t4,r,180-angle,180,#PB_Path_Relative|#PB_Path_Connected)

   ClosePath()

EndProcedure
Procedure AddPathShadow(x.d,y.d,w.d,h.d,r.d,angle.d,flags=#PB_Path_Default)

   Protected ro.d
   Protected t1.d,t2.d,t3.d,t4.d,t5.d

   ro=Min(Min(r,h/2),w/2)

   t1=Cos(angle*#PI/180);   1-89°
   t2=Sin(angle*#PI/180)
   t3=r*t1
   t4=r*t2
   t5=2*r-t4

   r=ro
   Debug ro

   MovePathCursor(x+w,y+h-r,flags)
   AddPathCircle(-r,0,r,0,90,#PB_Path_Relative)
   AddPathLine(-w+r*2,0,#PB_Path_Relative)
   AddPathCircle(0,-r,r,90,90+angle,#PB_Path_Relative|#PB_Path_Connected)
   AddPathLine(w-t5,0,#PB_Path_Relative)
   AddPathCircle(0,-t3,t3,90,0,#PB_Path_Relative|#PB_Path_Connected|#PB_Path_CounterClockwise)
   AddPathLine(0,-h+t5,#PB_Path_Relative)
   AddPathCircle(-t3,t4,r,360-angle,360,#PB_Path_Relative|#PB_Path_Connected)

   ClosePath()

EndProcedure

Procedure boxs(x,y,w,h,radius,col,extra=8)
 
  Protected alpha.f = 20
  Protected size = 20
  Protected offset.f = 5
  Protected color = $60000000
 
  For i=1 To size
     AddPathRoundBox( (x-(offset*(i/size))), (y-(offset*(i/size))), (w+i), (h+i), ((w+i)*radius/w) )
     VectorSourceColor(RGBA(Red(color), Green(color), Blue(color), alpha*((size-i)/size)))
     StrokePath(1)
  Next
 
   AddPathRoundBox(x,y,w,h,radius)
   VectorSourceColor($a0000000|col)
   FillPath(#PB_Path_Preserve)
   VectorSourceColor($60000000)
   StrokePath(1)

   VectorSourceColor($40ffffff)
   AddPathHighlight(x,y,w,h,radius,extra*2)
   FillPath()
   AddPathHighlight(x,y,w,h,radius,extra*3)
   FillPath()
   VectorSourceColor($20000000)
   AddPathShadow(x,y,w,h,radius,extra*2)
   FillPath()
   AddPathShadow(x,y,w,h,radius,extra*3)
   FillPath()


   ; Debug "Data.i "+Str(boxnr)+", "+Str(x)+","+Str(y)+", "+Str(w)+","+Str(h)+"; "+Str(size)

EndProcedure
Procedure show()

   Protected i

   StartVectorDrawing(CanvasVectorOutput(0))
   AddPathBox(0,0,VectorOutputWidth(),VectorOutputHeight())
   VectorSourceColor($Ff000000|#White)
   FillPath()
   
   ; some random background
   For i=0 To 1000
     AddPathBox(Random(VectorOutputWidth())-50,Random(VectorOutputHeight())-50, 50+Random(50), 50+Random(50))
     VectorSourceColor(RGBA(Random(255),Random(255),Random(255),Random(20)))
     FillPath()
   Next
   
   boxs(50,50,300,200,90,$F3D1AD)
   boxs(50,350,300,100,40,$F3D1AD,20);      smaller radius
   boxs(400,100,300,100,90,$9AF0B8)
   boxs(500,250,100,300,90,$9AF0B8,20)

   StopVectorDrawing()

EndProcedure

Procedure main()

   #X=800
   #Y=600

   OpenWindow(0,0,0,#X,#Y,"")
   CanvasGadget(0,0,0,#X,#Y)

   show()

   Repeat
      Select WaitWindowEvent()
      Case #PB_Event_CloseWindow
         End
;       Case #WM_CHAR
;          End
      EndSelect
   ForEver

EndProcedure
main()


Top
 Profile  
Reply with quote  
 Post subject: Re: Math and vector graphics
PostPosted: Sat Nov 10, 2018 4:36 pm 
Offline
Addict
Addict
User avatar

Joined: Thu Feb 09, 2006 11:27 pm
Posts: 2354
#Null, interestng approach, will also play around with your code now...

Tried to do clipping but that's not the best function in PB because it does not do alpha or antialiazing...

Code:
Procedure Min(a,b)
   If a<b
      ProcedureReturn a
   Else
      ProcedureReturn b
   EndIf
EndProcedure
Macro StartClipping()
   SaveVectorState()
   ClipPath()
EndMacro
Macro StopClipping()
   RestoreVectorState()
EndMacro

Procedure AddPathRoundBox(x.d,y.d,w.d,h.d,radius.d,flags=#PB_Path_Default)

   If radius>h/2 : radius=h/2 : EndIf
   If radius>w/2 : radius=w/2 : EndIf

   If radius<0
      radius=0
   EndIf

   MovePathCursor(x+radius,y,flags)

   AddPathArc(w-radius,0,w-radius,radius,radius,#PB_Path_Relative)
   AddPathArc(0,h-radius,-radius,h-radius,radius,#PB_Path_Relative)
   AddPathArc(-w+radius,0,-w+radius,-radius,radius,#PB_Path_Relative)
   AddPathArc(0,-h+radius,radius,-h+radius,radius,#PB_Path_Relative)

   ClosePath()

   MovePathCursor(-radius,0,#PB_Path_Relative)

EndProcedure
Procedure AddPathHighlight(x.d,y.d,w.d,h.d,r.d,angle.d,flags=#PB_Path_Default)

   Protected t1.d,t2.d,t3.d,t4.d,t5.d

   t1=Cos(angle*#PI/180);   1-89°
   t2=Sin(angle*#PI/180)
   t3=r*t1
   t4=r*t2
   t5=2*r-t4

   MovePathCursor(x,y+r,flags)
   AddPathCircle(r,0,r,180,270,#PB_Path_Relative)
   AddPathLine(w-r*2,0,#PB_Path_Relative)
   AddPathCircle(0,r,r,270,270+angle,#PB_Path_Relative|#PB_Path_Connected)
   AddPathLine(-w+t5,0,#PB_Path_Relative)
   AddPathCircle(0,t3,t3,270,180,#PB_Path_Relative|#PB_Path_Connected|#PB_Path_CounterClockwise)
   AddPathLine(0,h-t5,#PB_Path_Relative)
   AddPathCircle(t3,-t4,r,180-angle,180,#PB_Path_Relative|#PB_Path_Connected)

   ClosePath()

EndProcedure
Procedure AddPathShadow(x.d,y.d,w.d,h.d,r.d,angle.d,flags=#PB_Path_Default)

   Protected ro.d
   Protected t1.d,t2.d,t3.d,t4.d,t5.d

   ro=Min(Min(r,h/2),w/2)

   t1=Cos(angle*#PI/180);   1-89°
   t2=Sin(angle*#PI/180)
   t3=r*t1
   t4=r*t2
   t5=2*r-t4

   r=ro
   Debug ro

   MovePathCursor(x+w,y+h-r,flags)
   AddPathCircle(-r,0,r,0,90,#PB_Path_Relative)
   AddPathLine(-w+r*2,0,#PB_Path_Relative)
   AddPathCircle(0,-r,r,90,90+angle,#PB_Path_Relative|#PB_Path_Connected)
   AddPathLine(w-t5,0,#PB_Path_Relative)
   AddPathCircle(0,-t3,t3,90,0,#PB_Path_Relative|#PB_Path_Connected|#PB_Path_CounterClockwise)
   AddPathLine(0,-h+t5,#PB_Path_Relative)
   AddPathCircle(-t3,t4,r,360-angle,360,#PB_Path_Relative|#PB_Path_Connected)

   ClosePath()

EndProcedure
Procedure DrawVectorShadow(x.d,y.d,w.d,h.d,radius.d,size.d=20,offset.d=5,alpha.d=20,color=#Black,flags=#PB_Path_Default)

   Protected i
   AddPathBox(0,0,VectorOutputWidth(),VectorOutputHeight())
   AddPathRoundBox(x,y,w,h,radius)
   StartClipping()

   For i=1 To size
      AddPathRoundBox(x+offset-i,y+offset-i,w+i*2,h+i*2,((w+i)*radius/w) )
      VectorSourceColor(RGBA(Red(color), Green(color), Blue(color), alpha*((size-i)/size)))
      ;StrokePath(1)
      FillPath()
   Next
   StopClipping()

EndProcedure
Procedure boxs(x,y,w,h,radius,col,extra=8)

   DrawVectorShadow(x,y,w,h,radius,10,10,20)

   AddPathRoundBox(x,y,w,h,radius)
   VectorSourceColor($a0000000|col)
   FillPath(#PB_Path_Preserve)
   VectorSourceColor($60000000)
   StrokePath(1)

   If 0
      VectorSourceColor($40ffffff)
      AddPathHighlight(x,y,w,h,radius,extra*2)
      FillPath()
      AddPathHighlight(x,y,w,h,radius,extra*3)
      FillPath()
      VectorSourceColor($20000000)
      AddPathShadow(x,y,w,h,radius,extra*2)
      FillPath()
      AddPathShadow(x,y,w,h,radius,extra*3)
      FillPath()
   EndIf

   ; Debug "Data.i "+Str(boxnr)+", "+Str(x)+","+Str(y)+", "+Str(w)+","+Str(h)+"; "+Str(size)

EndProcedure
Procedure show()

   Protected i

   StartVectorDrawing(CanvasVectorOutput(0))
   AddPathBox(0,0,VectorOutputWidth(),VectorOutputHeight())
   VectorSourceColor($Ff000000|#White)
   FillPath()

   ; some random background
   If 0
      For i=0 To 1000
         AddPathBox(Random(VectorOutputWidth())-50,Random(VectorOutputHeight())-50, 50+Random(50), 50+Random(50))
         VectorSourceColor(RGBA(Random(255),Random(255),Random(255),Random(20)))
         FillPath()
      Next
   EndIf

   boxs(50,50,300,200,90,$F3D1AD)
   boxs(50,350,300,100,40,$F3D1AD,20);      smaller radius
   boxs(400,100,300,100,90,$9AF0B8)
   boxs(500,250,100,300,90,$9AF0B8,20)

   StopVectorDrawing()

EndProcedure

Procedure main()

   #X=800
   #Y=600

   OpenWindow(0,0,0,#X,#Y,"")
   CanvasGadget(0,0,0,#X,#Y)

   show()

   Repeat
      Select WaitWindowEvent()
      Case #PB_Event_CloseWindow
         End
         ;       Case #WM_CHAR
         ;          End
      EndSelect
   ForEver

EndProcedure
main()


Top
 Profile  
Reply with quote  
 Post subject: Re: Math and vector graphics
PostPosted: Sat Nov 10, 2018 5:56 pm 
Offline
Addict
Addict

Joined: Thu Aug 30, 2007 11:54 pm
Posts: 869
Location: right here
Looks pretty good :)
I think you could also use layers (BeginVectorLayer()). Overdrawing the shadow with the actual button by drawing the button completely opaque on top of the shadow, but both within a layer with its own transparency to blend everything with the background.

<edit>That would probably be more difficult if your buttons are drawn with multiple transparent parts on top of each other. But you could partially clear the shadow by drawing a opaque button background first. That would clear only the shadow within the layer and can be blended with the underlying background later.
But with the clipping it already looks fine anyway.


Top
 Profile  
Reply with quote  
 Post subject: Re: Math and vector graphics
PostPosted: Sat Nov 10, 2018 6:44 pm 
Offline
Addict
Addict

Joined: Thu Aug 30, 2007 11:54 pm
Posts: 869
Location: right here
As for the scrambled glow. If I add the radius correction from AddPathRoundBox() also to AddPathHighlight()..
Code:
   If r>h/2 : r=h/2 : EndIf
   If r>w/2 : r=w/2 : EndIf
..that seems to solve some of the issues.

<edit>
..and the same added for AddPathShadow() solves the other issue too?


Top
 Profile  
Reply with quote  
 Post subject: Re: Math and vector graphics
PostPosted: Sat Nov 10, 2018 8:01 pm 
Offline
Addict
Addict
User avatar

Joined: Thu Feb 09, 2006 11:27 pm
Posts: 2354
Some moments later...

Good idea about layers, which would be even more useful when an UnfillPath (Unstroke) function would also exist to allow erasing content from the layer (as said, clipping is not ideal because it's border are calculated pixel wise).

There's still a kind of light aura arround the buttons (could be seen best on the lower blue box), but the result is not that bad...

Code:
Procedure Min(a,b)
   If a<b
      ProcedureReturn a
   Else
      ProcedureReturn b
   EndIf
EndProcedure
Macro StartClipping()
   SaveVectorState()
   ClipPath()
EndMacro
Macro StopClipping()
   RestoreVectorState()
EndMacro

Procedure AddPathRoundBox(x.d,y.d,w.d,h.d,radius.d,flags=#PB_Path_Default)

   If radius>h/2 : radius=h/2 : EndIf
   If radius>w/2 : radius=w/2 : EndIf

   If radius<0
      radius=0
   EndIf

   MovePathCursor(x+radius,y,flags)

   AddPathArc(w-radius,0,w-radius,radius,radius,#PB_Path_Relative)
   AddPathArc(0,h-radius,-radius,h-radius,radius,#PB_Path_Relative)
   AddPathArc(-w+radius,0,-w+radius,-radius,radius,#PB_Path_Relative)
   AddPathArc(0,-h+radius,radius,-h+radius,radius,#PB_Path_Relative)

   ClosePath()

   MovePathCursor(-radius,0,#PB_Path_Relative)

EndProcedure
Procedure AddPathHighlight(x.d,y.d,w.d,h.d,r.d,angle.d,flags=#PB_Path_Default)

   Protected t1.d,t2.d,t3.d,t4.d,t5.d

   t1=Cos(angle*#PI/180);   1-89°
   t2=Sin(angle*#PI/180)
   t3=r*t1
   t4=r*t2
   t5=2*r-t4

   MovePathCursor(x,y+r,flags)
   AddPathCircle(r,0,r,180,270,#PB_Path_Relative)
   AddPathLine(w-r*2,0,#PB_Path_Relative)
   AddPathCircle(0,r,r,270,270+angle,#PB_Path_Relative|#PB_Path_Connected)
   AddPathLine(-w+t5,0,#PB_Path_Relative)
   AddPathCircle(0,t3,t3,270,180,#PB_Path_Relative|#PB_Path_Connected|#PB_Path_CounterClockwise)
   AddPathLine(0,h-t5,#PB_Path_Relative)
   AddPathCircle(t3,-t4,r,180-angle,180,#PB_Path_Relative|#PB_Path_Connected)

   ClosePath()

EndProcedure
Procedure AddPathShadow(x.d,y.d,w.d,h.d,r.d,angle.d,flags=#PB_Path_Default)

   Protected ro.d
   Protected t1.d,t2.d,t3.d,t4.d,t5.d

   ro=Min(Min(r,h/2),w/2)

   t1=Cos(angle*#PI/180);   1-89°
   t2=Sin(angle*#PI/180)
   t3=r*t1
   t4=r*t2
   t5=2*r-t4

   r=ro
   Debug ro

   MovePathCursor(x+w,y+h-r,flags)
   AddPathCircle(-r,0,r,0,90,#PB_Path_Relative)
   AddPathLine(-w+r*2,0,#PB_Path_Relative)
   AddPathCircle(0,-r,r,90,90+angle,#PB_Path_Relative|#PB_Path_Connected)
   AddPathLine(w-t5,0,#PB_Path_Relative)
   AddPathCircle(0,-t3,t3,90,0,#PB_Path_Relative|#PB_Path_Connected|#PB_Path_CounterClockwise)
   AddPathLine(0,-h+t5,#PB_Path_Relative)
   AddPathCircle(-t3,t4,r,360-angle,360,#PB_Path_Relative|#PB_Path_Connected)

   ClosePath()

EndProcedure
Procedure DrawVectorShadow(x.d,y.d,w.d,h.d,radius.d,size.d=20,offset.d=5,alpha.d=20,color=#Black,flags=#PB_Path_Default)

   Protected i
   AddPathBox(0,0,VectorOutputWidth(),VectorOutputHeight())
   AddPathRoundBox(x,y,w,h,radius)
   StartClipping()

   For i=1 To size
      AddPathRoundBox(x+offset-i,y+offset-i,w+i*2,h+i*2,((w+i)*radius/w) )
      VectorSourceColor(RGBA(Red(color), Green(color), Blue(color), Alpha/size))
      FillPath()
   Next
   StopClipping()

EndProcedure

Procedure boxs(x.f,y.f,w.f,h.f,radius.f,col,alpha=255,button.f=8,shadow.f=20,darkness=100,offset.f=15)

   Protected shadowcount=20

   radius=min(min(radius,h/2),w/2)

   BeginVectorLayer(min(alpha,255))
   
   ; Shadow
   shadow/shadowcount
   darkness=darkness/shadowcount+1
   For i=0 To shadowcount
      AddPathRoundBox(x+offset+shadow*i/2,y+offset+shadow*i/2,w-shadow*i,h-shadow*i,radius-shadow*(i-shadowcount/2)/2)
      VectorSourceColor(darkness<<24)
      FillPath()
   Next i

   ; Filled Button
   AddPathRoundBox(x,y,w,h,radius)
   VectorSourceColor($ff000000|col)
   FillPath()
   
   ; Erasing area...
   ;AddPathBox(x+50,y+50,150,50)
   ;VectorSourceColor($fffffffff)
   ;FillPath()
   
   ; Highlight and Shadow
   VectorSourceColor($40ffffff)
   AddPathHighlight(x,y,w,h,radius,button*2)
   FillPath()
   AddPathHighlight(x,y,w,h,radius,button*3)
   FillPath()
   VectorSourceColor($20000000)
   AddPathShadow(x,y,w,h,radius,button*2)
   FillPath()
   AddPathShadow(x,y,w,h,radius,button*3)
   FillPath()
   
   ; Button Border
   AddPathRoundBox(x,y,w,h,radius)
   VectorSourceColor($60000000)
   StrokePath(1)

   EndVectorLayer()

EndProcedure
Procedure show()

   Protected i

   StartVectorDrawing(CanvasVectorOutput(0))
   AddPathBox(0,0,VectorOutputWidth(),VectorOutputHeight())
   VectorSourceColor($Ff000000|#White)
   FillPath()

   ; some random background
   For i=0 To 100
      AddPathBox(Random(VectorOutputWidth())-50,Random(VectorOutputHeight())-50, 50+Random(50), 50+Random(50))
      VectorSourceColor(RGBA(Random(255),Random(255),Random(255),Random(40)))
      FillPath()
   Next

   boxs(50,50,300,200,90,$F3D1AD,160,5,50,170)
   boxs(50,350,300,100,40,$F3D1AD,200,8,20,50);      smaller radius
   boxs(400,100,300,100,90,$9AF0B8,120,10)
   boxs(500,250,100,300,90,$9AF0B8,180,20)

   StopVectorDrawing()

EndProcedure

Procedure main()

   #X=800
   #Y=600

   OpenWindow(0,0,0,#X,#Y,"")
   CanvasGadget(0,0,0,#X,#Y)

   show()

   Repeat
      Select WaitWindowEvent()
      Case #PB_Event_CloseWindow
         End
         ;       Case #WM_CHAR
         ;          End
      EndSelect
   ForEver

EndProcedure
main()


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 8 posts ] 

All times are UTC + 1 hour


Who is online

Users browsing this forum: No registered users and 13 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
Jump to:  

 


Powered by phpBB © 2008 phpBB Group
subSilver+ theme by Canver Software, sponsor Sanal Modifiye