Path Module (RoundBox, Hexagon, WaveLine, LoopLine)

Share your advanced PureBasic knowledge/code with the community.
User avatar
eddy
Addict
Addict
Posts: 1479
Joined: Mon May 26, 2003 3:07 pm
Location: Nantes

Path Module (RoundBox, Hexagon, WaveLine, LoopLine)

Post by eddy »

- PB 5.40
- shape: hexagon, roundbox
- option: 4 Corners Radius
- waves line
- loops line

Image

Code: Select all

DeclareModule PathAddons
   Enumeration
      #PB_WavePath_Default=0
      #PB_WavePath_Triangle
      #PB_WavePath_Square
      #PB_WavePath_Sine
      #PB_WavePath_Sawtooth
      
      #PB_LoopPath_Default=0
      #PB_LoopPath_Open
   EndEnumeration
   
   Declare PathWaveType(WaveType=#PB_WavePath_Default)
   Declare PathLoopType(LoopType=#PB_LoopPath_Default)
   Declare PathCornerRadius(x0.d, y0.d=#PB_Ignore, x1.d=#PB_Ignore, y1.d=#PB_Ignore, x2.d=#PB_Ignore, y2.d=#PB_Ignore, x3.d=#PB_Ignore, y3.d=#PB_Ignore)
   Declare AddPathRoundBox(x.d, y.d, Width.d, Height.d, Flags=#PB_Path_Default)
   Declare AddPathHexagon(x.d, y.d, Width.d, Height.d, Flags=#PB_Path_Default)
   Declare AddPathWaveLine(x.d, y.d, Count, Amplitude.d, Flags=#PB_Path_Default)
   Declare AddPathLoopLine(x.d, y.d, Count, Amplitude1.d, Amplitude2.d, Scale.d, Flags=#PB_Path_Default)
EndDeclareModule

Module PathAddons
   EnableExplicit
   Structure CORNER_RADIUS
      x.d
      y.d
   EndStructure
   Global CurrentWaveType=#PB_WavePath_Default
   Global CurrentLoopType=#PB_LoopPath_Default
   Global Dim CornerRadius.CORNER_RADIUS(3)
   
   Procedure PathWaveType(WaveType=#PB_WavePath_Default)
      CurrentWaveType=WaveType
   EndProcedure
   
   Procedure PathLoopType(LoopType=#PB_LoopPath_Default)
      CurrentLoopType=LoopType
   EndProcedure
   
   Procedure PathCornerRadius(x0.d, y0.d=#PB_Ignore, x1.d=#PB_Ignore, y1.d=#PB_Ignore, x2.d=#PB_Ignore, y2.d=#PB_Ignore, x3.d=#PB_Ignore, y3.d=#PB_Ignore)
      CornerRadius(0)\x=x0
      If y0=#PB_Ignore : y0=x0 : EndIf : CornerRadius(0)\y=y0
      
      If x1<>#PB_Ignore And y1<>#PB_Ignore And x2=#PB_Ignore And y2=#PB_Ignore And x3=#PB_Ignore And y3=#PB_Ignore
         x2=x1 : y2=y1
         x3=x1 : y3=y1
         x1=x0 : y1=y0
      EndIf
      
      If x1=#PB_Ignore : x1=x0 : EndIf : CornerRadius(1)\x=x1
      If y1=#PB_Ignore : y1=y0 : EndIf : CornerRadius(1)\y=y1
      
      If x2=#PB_Ignore : x2=x1 : EndIf : CornerRadius(2)\x=x2
      If y2=#PB_Ignore : y2=y1 : EndIf : CornerRadius(2)\y=y2
      
      If x3=#PB_Ignore : x3=x2 : EndIf : CornerRadius(3)\x=x3
      If y3=#PB_Ignore : y3=y2 : EndIf : CornerRadius(3)\y=y3
   EndProcedure
   
   Procedure AddPathRoundBox(x.d, y.d, Width.d, Height.d, Flags=#PB_Path_Default)
      MovePathCursor(x + CornerRadius(0)\x, y, Flags & #PB_Path_Relative)
      AddPathEllipse(0, CornerRadius(0)\y, CornerRadius(0)\x, CornerRadius(0)\y, 180, -90, #PB_Path_Relative)
      AddPathLine(Width-CornerRadius(0)\x-CornerRadius(1)\x, 0, #PB_Path_Relative)
      AddPathEllipse(0, CornerRadius(1)\y, CornerRadius(1)\x, CornerRadius(1)\y, -90, 0, #PB_Path_Connected | #PB_Path_Relative)
      AddPathLine(0, Height-CornerRadius(1)\y-CornerRadius(2)\y, #PB_Path_Relative)
      AddPathEllipse(-CornerRadius(2)\x, 0, CornerRadius(2)\x, CornerRadius(2)\y, 0, 90, #PB_Path_Connected | #PB_Path_Relative)
      AddPathLine(CornerRadius(2)\x + CornerRadius(3)\x-Width, 0, #PB_Path_Relative)
      AddPathEllipse(0, -CornerRadius(3)\y, CornerRadius(3)\x, CornerRadius(3)\y, 90, 180, #PB_Path_Connected | #PB_Path_Relative)
      ClosePath()
      MovePathCursor(0, -CornerRadius(0)\y, #PB_Path_Relative)
   EndProcedure
   
   Procedure AddPathHexagon(x.d, y.d, Width.d, Height.d, Flags=#PB_Path_Default)
      MovePathCursor(x, y + CornerRadius(0)\y, Flags & #PB_Path_Relative)
      AddPathLine(CornerRadius(0)\x, -CornerRadius(0)\y, #PB_Path_Relative)
      AddPathLine(Width-CornerRadius(0)\x-CornerRadius(1)\x, 0, #PB_Path_Relative)
      AddPathLine(CornerRadius(1)\x, CornerRadius(1)\y, #PB_Path_Relative)
      AddPathLine(0, Height-CornerRadius(1)\y-CornerRadius(2)\y, #PB_Path_Relative)
      AddPathLine(-CornerRadius(2)\x, CornerRadius(2)\y, #PB_Path_Relative)
      AddPathLine(CornerRadius(2)\x + CornerRadius(3)\x-Width, 0, #PB_Path_Relative)
      AddPathLine(-CornerRadius(3)\x, -CornerRadius(3)\y, #PB_Path_Relative)
      ClosePath()
      MovePathCursor(0, -CornerRadius(0)\y, #PB_Path_Relative)
   EndProcedure
   
   Procedure AddPathWaveLine(x.d, y.d, Count, Amplitude.d, Flags=#PB_Path_Default)
      If Count>0
         Protected.d xs=PathCursorX(), ys=PathCursorY() ;start pos
         Protected.d xd=x, yd=y                         ;destination pos
         Protected.d dx=(xd-xs), dy=(yd-ys)             ;distances
         If (Flags & #PB_Path_Relative) : dx=x : dy=y : EndIf
         Protected.d distHalf=Sqr(dx*dx + dy*dy) / Count / 2, distQuarter=distHalf / 2
         Protected.i i
         
         SaveVectorState()
         RotateCoordinates(xs, ys, Degree(ATan2(dx, dy)))
         Select CurrentWaveType
            Case #PB_WavePath_Default
               For i=1 To Count
                  AddPathCurve(distQuarter, -Amplitude, distQuarter, -Amplitude, distHalf, 0, #PB_Path_Relative)
                  AddPathCurve(distQuarter, Amplitude, distQuarter, Amplitude, distHalf, 0, #PB_Path_Relative)
               Next
            Case #PB_WavePath_Triangle
               For i=1 To Count
                  AddPathLine(distQuarter, -Amplitude, #PB_Path_Relative)
                  AddPathLine(distHalf, 2*Amplitude, #PB_Path_Relative)
                  AddPathLine(distQuarter, -Amplitude, #PB_Path_Relative)
               Next
            Case #PB_WavePath_Square
               For i=1 To Count
                  AddPathLine(0, -Amplitude, #PB_Path_Relative)
                  AddPathLine(distHalf, 0, #PB_Path_Relative)
                  AddPathLine(0, 2*Amplitude, #PB_Path_Relative)
                  AddPathLine(distHalf, 0, #PB_Path_Relative)
                  AddPathLine(0, -Amplitude, #PB_Path_Relative)
               Next
            Case #PB_WavePath_Sawtooth
               For i=1 To Count
                  AddPathLine(distHalf, -Amplitude, #PB_Path_Relative)
                  AddPathLine(0, 2*Amplitude, #PB_Path_Relative)
                  AddPathLine(distHalf, -Amplitude, #PB_Path_Relative)
               Next
            Case #PB_WavePath_Sine
               For i=1 To Count
                  AddPathCurve(distQuarter / 2, -Amplitude / 2, 1.5*distQuarter, -Amplitude / 2, distHalf, 0, #PB_Path_Relative)
                  AddPathCurve(distQuarter / 2, Amplitude / 2, 1.5*distQuarter, Amplitude / 2, distHalf, 0, #PB_Path_Relative)
                  
                  ;AddPathEllipse(distQuarter, 0, distQuarter, Amplitude, 180, 360, #PB_Path_Relative)
                  ;AddPathEllipse(distQuarter, 0, distQuarter, Amplitude, 180, 0, #PB_Path_Relative | #PB_Path_CounterClockwise)
               Next
         EndSelect
         RestoreVectorState()
      EndIf
   EndProcedure
   
   Procedure AddPathLoopLine(x.d, y.d, Count, Amplitude1.d, Amplitude2.d, Scale.d, Flags=#PB_Path_Default)
      If Count>0
         Protected.d xs=PathCursorX(), ys=PathCursorY() ;start pos
         Protected.d xd=x, yd=y                         ;destination pos
         Protected.d dx=(xd-xs), dy=(yd-ys)             ;distances
         If (Flags & #PB_Path_Relative) : dx=x : dy=y : EndIf
         Protected.d distHalf=Sqr(dx*dx + dy*dy) / 2, dist1, dist2, k=1 / Scale
         Protected.i i
         SaveVectorState()
         RotateCoordinates(xs, ys, Degree(ATan2(dx, dy)))
         Select CurrentLoopType
            Case #PB_LoopPath_Default
               dist1=k*distHalf / (Count*(k-1) + k)
               dist2=dist1 / k
               AddPathEllipse(dist1, 0, dist1, Amplitude1, -180, 0, #PB_Path_Connected | #PB_Path_Relative)
               For i=1 To Count
                  AddPathEllipse(-dist2, 0, dist2, Amplitude2, 0, 180, #PB_Path_Connected | #PB_Path_Relative)
                  AddPathEllipse(dist1, 0, dist1, Amplitude1, -180, 0, #PB_Path_Connected | #PB_Path_Relative)
               Next
            Case #PB_LoopPath_Open
               Count + 1
               dist1=k*distHalf / (Count*(k-1))
               dist2=dist1 / k
               For i=1 To Count
                  AddPathEllipse(dist1, 0, dist1, Amplitude1, -180, 0, #PB_Path_Connected | #PB_Path_Relative)
                  AddPathEllipse(-dist2, 0, dist2, Amplitude2, 0, 180, #PB_Path_Connected | #PB_Path_Relative)
               Next
         EndSelect
         RestoreVectorState()
      EndIf
   EndProcedure
EndModule

; ********************
; EXAMPLE
; ********************

UseModule PathAddons

Procedure DrawCurves()
   Protected startOffset.d=10.0*ElapsedMilliseconds() / 1000
   
   If StartVectorDrawing(CanvasVectorOutput(0))
      ; --------------------------------------------
      ; enable 2X zoom
      ScaleCoordinates(2, 2)
      
      ; --------------------------------------------
      ; draw white background
      VectorSourceColor(RGBA(255, 255, 255, 255))
      FillVectorOutput()
      
      ; --------------------------------------------
      ; draw loop lines
      Define.d x=100, y=130
      Define amplitude.d=10, count.i=3
      
      MovePathCursor(x, y)
      PathLoopType(#PB_LoopPath_Default)
      AddPathLoopLine(70, 60, count, amplitude / 2, amplitude / 3, 0.2, #PB_Path_Relative)
      VectorSourceColor(RGBA(255, 90, 90, 255))
      StrokePath(2, #PB_Path_RoundEnd)
      
      MovePathCursor(x, y)
      PathLoopType(#PB_LoopPath_Default)
      AddPathLoopLine(70, 60, count, amplitude, amplitude, 0.4, #PB_Path_Relative)
      VectorSourceColor(RGBA(38, 255, 0, 140))
      StrokePath(3, #PB_Path_RoundEnd)
      
      MovePathCursor(x + 20, y)
      PathLoopType(#PB_LoopPath_Open)
      AddPathLoopLine(70, 60, count, amplitude / 2, amplitude / 3, 0.2, #PB_Path_Relative)
      VectorSourceColor(RGBA(0, 251, 255, 200))
      StrokePath(3, #PB_Path_RoundEnd)
      
      ; --------------------------------------------
      ; draw dash line
      Define.d x=10, y=90
      MovePathCursor(x, y)
      AddPathLine(90, 90, #PB_Path_Relative)
      VectorSourceColor(RGBA(255, 0, 50, 255))
      DashPath(2, 5)
      
      ; --------------------------------------------
      ; draw wave lines
      Define amplitude.d=20, count.i=2
      MovePathCursor(x, y)
      PathWaveType(#PB_WavePath_Default)
      AddPathWaveLine(90, 90, count, amplitude, #PB_Path_Relative)
      VectorSourceColor(RGBA(255, 90, 90, 255))
      StrokePath(3, #PB_Path_RoundEnd)
      
      MovePathCursor(x, y)
      PathWaveType(#PB_WavePath_Sawtooth)
      AddPathWaveLine(90, 90, count, amplitude, #PB_Path_Relative)
      VectorSourceColor(RGBA(0, 251, 255, 200))
      StrokePath(3, #PB_Path_RoundEnd)
      
      MovePathCursor(x, y)
      PathWaveType(#PB_WavePath_Sine)
      AddPathWaveLine(90, 90, count, amplitude, #PB_Path_Relative)
      VectorSourceColor(RGBA(185, 0, 255, 100))
      StrokePath(3, #PB_Path_RoundEnd)
      
      MovePathCursor(x, y)
      PathWaveType(#PB_WavePath_Square)
      AddPathWaveLine(90, 90, count, amplitude, #PB_Path_Relative)
      VectorSourceColor(RGBA(38, 255, 0, 140))
      StrokePath(3, #PB_Path_RoundEnd)
      
      MovePathCursor(x, y)
      PathWaveType(#PB_WavePath_Triangle)
      AddPathWaveLine(90, 90, count, amplitude, #PB_Path_Relative)
      VectorSourceColor(RGBA(60, 100, 200, 200))
      DotPath(3, 5, #PB_Path_RoundEnd, startOffset)
      
      ; --------------------------------------------
      ; draw round boxs
      PathCornerRadius(10)
      AddPathRoundBox(10, 10, 50, 50)
      
      PathCornerRadius(10, 20)
      AddPathRoundBox(60, 0, 50, 50, #PB_Path_Relative)
      
      PathCornerRadius(25, 20, 20, 10)
      AddPathRoundBox(60, 0, 50, 50, #PB_Path_Relative)
      
      PathCornerRadius(10, 20, 20, 10, 20, 10)
      AddPathRoundBox(0, 60, 50, 50, #PB_Path_Relative)
      
      PathCornerRadius(25, 40, 10, 10, 25, 40, 10, 10)
      AddPathRoundBox(-60, 0, 50, 50, #PB_Path_Relative)
      
      VectorSourceColor(RGBA(255, 90, 90, 255))
      StrokePath(3, #PB_Path_RoundEnd)
      
      ; --------------------------------------------
      ; draw hexagons on Layer
      BeginVectorLayer(200)
      PathCornerRadius(10)
      AddPathHexagon(10, 10, 50, 50)
      
      PathCornerRadius(10, 20)
      AddPathHexagon(60, 0, 50, 50, #PB_Path_Relative)
      
      PathCornerRadius(25, 20, 20, 10)
      AddPathHexagon(60, 0, 50, 50, #PB_Path_Relative)
      
      PathCornerRadius(10, 20, 20, 10, 20, 10)
      AddPathHexagon(0, 60, 50, 50, #PB_Path_Relative)
      
      PathCornerRadius(25, 40, 10, 10, 25, 40, 10, 10)
      AddPathHexagon(-60, 0, 50, 50, #PB_Path_Relative)
      
      VectorSourceColor(RGBA(60, 100, 200, 255))
      DotPath(3, 5, #PB_Path_RoundEnd, startOffset)
      EndVectorLayer()
      
      StopVectorDrawing()
   EndIf
EndProcedure


If OpenWindow(0, 0, 0, 400, 400, "Animated Vector Drawing", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
   CanvasGadget(0, 0, 0, 400, 400)
   AddWindowTimer(0, 100, 1000 / 30)
   BindEvent(#PB_Event_Timer, @DrawCurves())
   
   Repeat
      Event=WaitWindowEvent()
   Until Event=#PB_Event_CloseWindow
EndIf
Last edited by eddy on Fri Sep 18, 2015 6:26 pm, edited 8 times in total.
Imagewin10 x64 5.72 | IDE | PB plugin | Tools | Sprite | JSON | visual tool
said
Enthusiast
Enthusiast
Posts: 342
Joined: Thu Apr 14, 2011 6:07 pm

Re: Path Module (RoundBox, Hexagon)

Post by said »

Nice! Thanks for sharing, the new Vector library seems very interesting :D i hope i can find some time soon to test it out.
davido
Addict
Addict
Posts: 1890
Joined: Fri Nov 09, 2012 11:04 pm
Location: Uttoxeter, UK

Re: Path Module (RoundBox, Hexagon)

Post by davido »

@eddy,
Very nice, thank you for sharing. :D
Looks great on Windows 7

Incidentally, I assume you wrote it for Windows OS.
But I cannot see why it shouldn't look the same on Mac OS X, however, it looks very different.
DE AA EB
User avatar
eddy
Addict
Addict
Posts: 1479
Joined: Mon May 26, 2003 3:07 pm
Location: Nantes

Re: Path Module (RoundBox, Hexagon)

Post by eddy »

davido wrote:@eddy,
Very nice, thank you for sharing. :D
Looks great on Windows 7

Incidentally, I assume you wrote it for Windows OS.
But I cannot see why it shouldn't look the same on Mac OS X, however, it looks very different.
What kind of differences ? (shape or color)
Imagewin10 x64 5.72 | IDE | PB plugin | Tools | Sprite | JSON | visual tool
User avatar
eddy
Addict
Addict
Posts: 1479
Joined: Mon May 26, 2003 3:07 pm
Location: Nantes

Re: Path Module (RoundBox, Hexagon)

Post by eddy »

Updated
- PathWaveType : default, sine, square, triangle, sawtooth
- AddPathWaveLine
Imagewin10 x64 5.72 | IDE | PB plugin | Tools | Sprite | JSON | visual tool
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3942
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: Path Module (RoundBox, Hexagon)

Post by wilbert »

davido wrote:Incidentally, I assume you wrote it for Windows OS.
But I cannot see why it shouldn't look the same on Mac OS X, however, it looks very different.
It shouldn't be this different.
Fred should take a look at this because this definitely is a bug !
Windows (x64)
Raspberry Pi OS (Arm64)
davido
Addict
Addict
Posts: 1890
Joined: Fri Nov 09, 2012 11:04 pm
Location: Uttoxeter, UK

Re: Path Module (RoundBox, Hexagon)

Post by davido »

@wilbert,
Thank you for your comments, I'll just check with eddy, first.
@eddy,
This is what it looks like on the Mac.
If you think it is a bug, I will so post it. However, I don't wish to overburden Fred with none-bugs.
Image

Is there some way to specify the picture size in the url tags?
Last edited by davido on Sun Sep 06, 2015 11:46 am, edited 1 time in total.
DE AA EB
User avatar
Vera
Addict
Addict
Posts: 858
Joined: Tue Aug 11, 2009 1:56 pm
Location: Essen (Germany)

Re: Path Module (RoundBox, Hexagon)

Post by Vera »

davido wrote:Is there some way to specify the picture size in the url tags?
No.
Unfortunately tinypic doesn't provide different sizes after you've uploaded a picture. You would have to preset/choose the size before submitting.
But I figured out a trick: you could use the thumbnail preview of your picture and embrace it within URL-tags leading to the original image. (seems only '_th' has to be added to the image-name to get hold of it)

edit: [removed imaged-image-link to slim posting]
This is how it will appear with the BB-code like this: (ready for you to copy if you'd like to use it in your posting)

Code: Select all

[url=http://i62.tinypic.com/jqrn68.png][img]http://i62.tinypic.com/jqrn68_th.png[/img][/url]
edit: @davido ~ You're welcome ~ it was my pleasure Image
Last edited by Vera on Sun Sep 06, 2015 12:44 pm, edited 1 time in total.
davido
Addict
Addict
Posts: 1890
Joined: Fri Nov 09, 2012 11:04 pm
Location: Uttoxeter, UK

Re: Path Module (RoundBox, Hexagon)

Post by davido »

@Vera,

Now that was clever.
Thank you, very much.
I've corrected my post. :D

@eddy,
Thank you for posting the bug report.
DE AA EB
User avatar
eddy
Addict
Addict
Posts: 1479
Joined: Mon May 26, 2003 3:07 pm
Location: Nantes

Re: Path Module (RoundBox, Hexagon, WaveLine)

Post by eddy »

Updated
- PathLoopType : default, open
- AddLoopWaveLine
Imagewin10 x64 5.72 | IDE | PB plugin | Tools | Sprite | JSON | visual tool
User avatar
Erlend
Enthusiast
Enthusiast
Posts: 115
Joined: Mon Apr 19, 2004 8:22 pm
Location: NORWAY

Re: Path Module (RoundBox, Hexagon, WaveLine, LoopLine)

Post by Erlend »

A quick test shows a difference between windows and linux. Seems the DotPath() command is a bit "off", if I change the code to say "DotPath(3,4)" instead of "DotPath(3,1)" as in eddy 's code. The result is the same, so the distance parameter of DotPath is handled different on the two OS's, could someone confirm this so we can add that to bug lit??
Image
collectordave
Addict
Addict
Posts: 1310
Joined: Fri Aug 28, 2015 6:10 pm
Location: Portugal

Re: Path Module (RoundBox, Hexagon, WaveLine, LoopLine)

Post by collectordave »

Hi eddy

Great. Do you mind if I try to incorporate these into my Print and Preview Module?

Cheers
Any intelligent fool can make things bigger and more complex. It takes a touch of genius — and a lot of courage to move in the opposite direction.
User avatar
eddy
Addict
Addict
Posts: 1479
Joined: Mon May 26, 2003 3:07 pm
Location: Nantes

Re: Path Module (RoundBox, Hexagon, WaveLine, LoopLine)

Post by eddy »

collectordave wrote:Hi eddy

Great. Do you mind if I try to incorporate these into my Print and Preview Module?

Cheers
Feel free to use it
Imagewin10 x64 5.72 | IDE | PB plugin | Tools | Sprite | JSON | visual tool
collectordave
Addict
Addict
Posts: 1310
Joined: Fri Aug 28, 2015 6:10 pm
Location: Portugal

Re: Path Module (RoundBox, Hexagon, WaveLine, LoopLine)

Post by collectordave »

Thanks eddy,

Pushed me in the right direction.

Now have a routine for displaying and printing all regular polygons from triangle to decagon and working on other complex shapes.
Any intelligent fool can make things bigger and more complex. It takes a touch of genius — and a lot of courage to move in the opposite direction.
freak
PureBasic Team
PureBasic Team
Posts: 5941
Joined: Fri Apr 25, 2003 5:21 pm
Location: Germany

Re: Path Module (RoundBox, Hexagon, WaveLine, LoopLine)

Post by freak »

Please note the changes here: http://www.purebasic.fr/english/viewtop ... 92#p471992

The DotPath() command above must be adjusted to have a larger 'Distance'. Otherwise it looks like a solid line.
quidquid Latine dictum sit altum videtur
Post Reply