
Code: Select all
DeclareModule PathGuide
Declare.i AddPathAnchor(Position.d, Flags=#PB_Relative)
Declare AnchorCoordinates(PathAnchor)
Declare.d PathAnchorX(PathAnchor)
Declare.d PathAnchorY(PathAnchor)
Declare.d PathAnchorAngle(PathAnchor)
Declare.d PathAnchorPos(PathAnchor, Flags=#PB_Relative)
EndDeclareModule
Module PathGuide
Structure PATH_ANCHOR
pos.d
percent.d
x.d
y.d
a.d
EndStructure
Global NewList PathAnchors.PATH_ANCHOR()
Procedure.i AddPathAnchor(Position.d, Flags=#PB_Relative)
If Flags=#PB_Relative : Position=PathLength()*Position : EndIf
Protected *PathAnchor.PATH_ANCHOR=AddElement(PathAnchors())
With *PathAnchor
\pos=Position
\percent=Position / PathLength()
\x=PathPointX(Position)
\y=PathPointY(Position)
\a=PathPointAngle(Position)
EndWith
ProcedureReturn *PathAnchor
EndProcedure
Procedure.d PathAnchorX(*PathAnchor.PATH_ANCHOR)
ProcedureReturn *PathAnchor\x
EndProcedure
Procedure.d PathAnchorY(*PathAnchor.PATH_ANCHOR)
ProcedureReturn *PathAnchor\y
EndProcedure
Procedure.d PathAnchorAngle(*PathAnchor.PATH_ANCHOR)
ProcedureReturn *PathAnchor\a
EndProcedure
Procedure.d PathAnchorPos(*PathAnchor.PATH_ANCHOR, Flags=#PB_Relative)
If (Flags=#PB_Relative)
ProcedureReturn *PathAnchor\percent
Else
ProcedureReturn *PathAnchor\pos
EndIf
EndProcedure
Procedure AnchorCoordinates(*PathAnchor.PATH_ANCHOR)
With *PathAnchor
ResetCoordinates()
TranslateCoordinates(\x, \y)
RotateCoordinates(0, 0, \a)
EndWith
EndProcedure
EndModule
CompilerIf #PB_Compiler_IsMainFile
; ********************
; EXAMPLE
; ********************
UseModule PathGuide
Procedure AddDecoratedPath(type$, x0.d, y0.d, x1.d, y1.d, x2.d, y2.d, x.d, y.d, offset.d, color1, color2)
;path (extract anchors)
MovePathCursor(x0, y0)
AddPathCurve(x1, y1, x2, y2, x, y)
PathLength=PathLength()
Dim anchors(3)
anchors(1)=AddPathAnchor(Mod(0.66 + offset, 1))
anchors(2)=AddPathAnchor(Mod(0.33 + offset, 1))
anchors(3)=AddPathAnchor(Mod(0.00 + offset, 1))
VectorSourceColor(color1)
StrokePath(10, #PB_Path_RoundEnd)
;arrow heads
SaveVectorState()
Select type$
Case "ArrowHead"
Length.d=19
Width.d=20
For i=1 To ArraySize(anchors())
AnchorCoordinates(anchors(i))
MovePathCursor(-Length, -Width)
AddPathLine(0, 0)
AddPathLine(-Length, Width)
Next
VectorSourceColor(color2)
StrokePath(15, #PB_Path_RoundCorner)
Case "Letter"
VectorFont(FontID(0), 50)
For i=1 To ArraySize(anchors())
AnchorCoordinates(anchors(i))
MovePathCursor(0, 0)
AddPathText("A")
Next
VectorSourceColor(color2)
StrokePath(5)
Case "Dot"
For i=1 To ArraySize(anchors())
AnchorCoordinates(anchors(i))
MovePathCursor(0, 0)
radius=50 - 45*PathAnchorPos(anchors(i))
AddPathCircle(0, 0, radius)
Next
VectorSourceColor(RGBA(255, 255, 255, 255))
FillPath(#PB_Path_Preserve)
VectorSourceColor(color2)
StrokePath(5)
EndSelect
RestoreVectorState()
EndProcedure
Procedure Draw()
Static k.d
k + 30 / 1000.0
If StartVectorDrawing(CanvasVectorOutput(0))
;fill background color
VectorSourceColor(RGBA(255, 255, 255, 255))
FillVectorOutput()
;decorated paths
x.d=WindowMouseX(0)
y.d=WindowMouseY(0)
AddDecoratedPath("Letter", 50, 100, 90, 30, 250, 180, x, y, k, RGBA(150, 171, 255, 225), RGBA(255, 150, 173, 206))
AddDecoratedPath("ArrowHead", 500, 350, 400, 320, x + 100, y-20, x, y, k, RGBA(255, 19, 73, 206), RGBA(255, 19, 246, 145))
AddDecoratedPath("Dot", 50, 350, x, 300, x, y + 50, x, y, k, RGBA(19, 255, 25, 145), RGBA(204, 255, 19, 145))
;target
MovePathCursor(x, y)
AddPathCircle(x, y, 20)
VectorSourceColor(RGBA(50, 120, 170, 200))
DashPath(5, PathLength() / 12, #PB_Path_RoundEnd, k*100)
StopVectorDrawing()
EndIf
EndProcedure
LoadFont(0, "Arial", 14)
If OpenWindow(0, 0, 0, 600, 400, "Vector2D: complex path drawing", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
AddWindowTimer(0, 1, 1000 / 30)
CanvasGadget(0, 0, 0, WindowWidth(0), WindowHeight(0))
BindEvent(#PB_Event_Timer, @Draw())
Repeat: Until WaitWindowEvent()=#PB_Event_CloseWindow
EndIf
CompilerEndIf