Voici un algorithme qui peut vous être utile pour dessiner une courbe de bezier ou tester la présence de la souris sur un courbe existante
Code : Tout sélectionner
Procedure cubicBezier(Array p(2),t.f,*x,*y)
; this procedure return the dot of curve
; base on the casteljau algorithm
; p is a array (2,4) one as x,y second is p0,p1,p2,p3
; t is a float batween 0 and 1
Protected Dim dot(2),i
For i = 0 To 1
dot(i) = Pow(1 - t,3) * p(i,0) + Pow(1 - t,2) * 3 * t * p(i,1) +
(1 - t) * 3 * t * t * p(i,2) + t * t* t * p(i,3)
Next
PokeL(*x,dot(0))
PokeL(*y,dot(1))
EndProcedure
Exemple complet :
Code : Tout sélectionner
Global Dim p(2,4)
#X = 0
#Y = 1
#MAIN_FORM = 0
Enumeration
#CANVAS
#BT_DRAW
#P0X
#P0Y
#P1X
#P1Y
#P2X
#P2Y
#P3X
#P3Y
EndEnumeration
; cursor pos
p(#X,0) = 50
p(#Y,0) = 50
; p1 pos
p(#X,1) = 100
p(#Y,1) = 10
; p2 pos
p(#X,2) = 300
p(#Y,2) = 250
; p3 pos
p(#X,3) = 400
p(#Y,3) = 150
Declare drawDots()
Declare cubicBezier(Array p(2),t.f,*x,*y)
Procedure drawCurve()
StartVectorDrawing(CanvasVectorOutput(#CANVAS))
VectorSourceColor($FFD2FAFA)
FillVectorOutput()
; draw curve
MovePathCursor(p(#x,0),p(#Y,0))
AddPathCurve(p(#x,1),p(#Y,1),p(#x,2),p(#Y,2),p(#x,3),p(#Y,3))
VectorSourceColor($FF0000FF)
StrokePath(2)
; draw control dots
VectorSourceColor($8D0000FF)
AddPathBox(p(#x,1),p(#Y,1),10,10)
AddPathBox(p(#x,2),p(#Y,2),10,10)
FillPath()
StopVectorDrawing()
EndProcedure
Procedure hoverCurve(mx,my)
Protected t.f = 0,n,x,y
For n = 0 To 1 / 0.01
cubicBezier(p(),t,@x,@y)
If mx >= x - 1 And mx <= x + 1
If my >= y - 1 And my <= y + 1
ProcedureReturn #True
EndIf
EndIf
t + 0.01
Next
ProcedureReturn #False
EndProcedure
Procedure cubicBezier(Array p(2),t.f,*x,*y)
; this procedure return the dot of curve
; base on the casteljau algorithm
; p is a array (2,4) one as x,y second is p0,p1,p2,p3
; t is a float batween 0 and 1
Protected Dim dot(2),i
For i = 0 To 1
dot(i) = Pow(1 - t,3) * p(i,0) + Pow(1 - t,2) * 3 * t * p(i,1) +
(1 - t) * 3 * t * t * p(i,2) + t * t* t * p(i,3)
Next
PokeL(*x,dot(0))
PokeL(*y,dot(1))
EndProcedure
Procedure drawDots()
Protected x,y,t.f = 0,n
For n = 0 To 1 / 0.01
StartVectorDrawing(CanvasVectorOutput(#CANVAS))
VectorSourceColor($FF00FF00)
cubicBezier(p(),t,@x,@y)
AddPathCircle(x,y,3)
t + 0.01
FillPath()
StopVectorDrawing()
Delay(50)
Next
EndProcedure
Procedure evGadget()
Select EventGadget()
Case #P0X
p(#X,0) = GetGadgetState(EventGadget())
drawCurve()
Case #P0Y
p(#Y,0) = GetGadgetState(EventGadget())
drawCurve()
Case #P1X
p(#X,1) = GetGadgetState(EventGadget())
drawCurve()
Case #P1Y
p(#Y,1) = GetGadgetState(EventGadget())
drawCurve()
Case #P2X
p(#X,2) = GetGadgetState(EventGadget())
drawCurve()
Case #P2Y
p(#Y,2) = GetGadgetState(EventGadget())
drawCurve()
Case #P3X
p(#X,3) = GetGadgetState(EventGadget())
drawCurve()
Case #P3Y
p(#Y,3) = GetGadgetState(EventGadget())
drawCurve()
Case #BT_DRAW
drawDots()
Case #CANVAS
If EventType() = #PB_EventType_MouseMove
Protected mx = GetGadgetAttribute(#CANVAS,#PB_Canvas_MouseX)
Protected my = GetGadgetAttribute(#CANVAS,#PB_Canvas_MouseY)
If hoverCurve(mx,my)
SetGadgetAttribute(#CANVAS,#PB_Canvas_Cursor,#PB_Cursor_Hand)
Else
SetGadgetAttribute(#CANVAS,#PB_Canvas_Cursor,#PB_Cursor_Default)
EndIf
EndIf
EndSelect
EndProcedure
OpenWindow(#MAIN_FORM,0,0,800,600,"Event curve",#PB_Window_ScreenCentered|#PB_Window_SystemMenu)
CanvasGadget(#CANVAS,0,0,800,530)
; PO
y = 540
x = 10
TextGadget(#PB_Any,X,Y,60,20,"P0 X :")
X + 60
SpinGadget(#P0X,X,Y,60,20,0,1000,#PB_Spin_Numeric)
SetGadgetState(#P0X,p(#x,0))
Y + 30
X = 10
TextGadget(#PB_Any,X,Y,60,20,"P0 Y :")
X + 60
SpinGadget(#P0Y,X,Y,60,20,0,1000,#PB_Spin_Numeric)
SetGadgetState(#P0Y,p(#Y,0))
; P1
y = 540
x = 150
TextGadget(#PB_Any,X,Y,60,20,"P1 X :")
X + 60
SpinGadget(#P1X,X,Y,60,20,0,1000,#PB_Spin_Numeric)
SetGadgetState(#P1X,p(#x,1))
Y + 30
X = 150
TextGadget(#PB_Any,X,Y,60,20,"P1 Y :")
X + 60
SpinGadget(#P1Y,X,Y,60,20,0,1000,#PB_Spin_Numeric)
SetGadgetState(#P1Y,p(#Y,1))
; P2
y = 540
x = 300
TextGadget(#PB_Any,X,Y,60,20,"P2 X :")
X + 60
SpinGadget(#P2X,X,Y,60,20,0,1000,#PB_Spin_Numeric)
SetGadgetState(#P2X,p(#x,2))
Y + 30
X = 300
TextGadget(#PB_Any,X,Y,60,20,"P2 Y :")
X + 60
SpinGadget(#P2Y,X,Y,60,20,0,1000,#PB_Spin_Numeric)
SetGadgetState(#P2Y,p(#Y,2))
; P3
y = 540
x = 450
TextGadget(#PB_Any,X,Y,60,20,"P3 X :")
X + 60
SpinGadget(#P3X,X,Y,60,20,0,1000,#PB_Spin_Numeric)
SetGadgetState(#P3X,p(#x,3))
Y + 30
X = 450
TextGadget(#PB_Any,X,Y,60,20,"P3 Y :")
X + 60
SpinGadget(#P3Y,X,Y,60,20,0,1000,#PB_Spin_Numeric)
SetGadgetState(#P3Y,p(#Y,3))
y = 540
x + 70
ButtonGadget(#BT_DRAW,x,y,60,30,"DRAW")
drawCurve()
BindEvent(#PB_Event_Gadget,@evGadget())
Repeat
WaitWindowEvent()
Until Event() = #PB_Event_CloseWindow