comtois a écrit :graph100 a écrit :Cette nouvelle procedure est vraiment, vraiment plus lente.
dessiner avec des cercles est très couteux en temps !
C'est clair, dessiner des cercles perd tout l'intérêt de l'algo de bresenham . La mise en oeuvre de l'algo modifié est moins simple mais sûrement plus efficace
Ce n'est pas une question de créneaux. Cet algo permet de parcourir la surface du trait épais qu'une seule fois !
Bref, un code est plus clair :
-> ma fonction WideLine() modifiée pour aller 2*fois plus vite (qu'avant)
-> la fonction bresenhamLine() qui est en règle générale un peu plus rapide. (mais pas bcp, et sérieusement, pour la galère que c'est à faire, je préfère l'autre)
Le tout dans un module "Draw".
Je me suis dis que si on faisait d'autres fonctions de dessin "native" PB, ça pourrait être intéressant de les regrouper dans un seul module !
Code : Tout sélectionner
DeclareModule Draw
Declare WideLine(x1,y1,x2,y2, Thickness, color = 0)
Declare BresenhamLine(x0 ,y0 ,x1 ,y1, Thickness, Color = 0)
EndDeclareModule
Module Draw
Procedure WideLine(x1,y1,x2,y2, Thickness, color = 0)
If Thickness = 0
LineXY(x1, y1, x2, y2, color)
ProcedureReturn
Else
Circle(x2, y2, Thickness, color)
EndIf
Protected.l j, l, ol, n, i
Protected r2.d = Thickness * Thickness, tmp.d
j = -Thickness - 1
u.d = x2 - x1
v.d = y2 - y1
ol = 0
Repeat
j + 1
tmp = r2 - j * j
If tmp < 0
If j > 0
Break
EndIf
Else
l = Sqr(tmp)
n = Sign(l - ol)
i = ol - n
Repeat
i + n
tmp = - v * j
If tmp + u * i >= 0
LineXY(x1 - i, y1 + j, x2 - i, y2 + j, color)
EndIf
If tmp - u * i >= 0
LineXY(x1 + i, y1 + j, x2 + i, y2 + j, color)
EndIf
Until(n = 1 And i >= l) Or (n = -1 And i <= l) Or n = 0
EndIf
ol = l
ForEver
EndProcedure
Procedure BresenhamLine(x0 ,y0 ,x1 ,y1, Thickness, Color = 0)
If Thickness = 0 ;Suggestion de kernadec
LineXY(x1, y1, x0, y0 , color)
Else
Circle(x0, y0, Thickness, Color)
Circle(x1, y1, Thickness, Color)
;Suggestion de comtois : l'algorithme de Bresenham
If Abs(y1 - y0) > Abs(x1 - x0)
steep =#True
Swap x0, y0
Swap x1, y1
EndIf
If x0 > x1
Swap x0, x1
Swap y0, y1
EndIf
deltax = x1 - x0
deltay = Abs(y1 - y0)
L.d = Sqr(deltax * deltax + deltay * deltay)
If L < 2
ProcedureReturn
EndIf
error = deltax / 2
If y0 < y1
ystep = 1
Else
ystep = -1
EndIf
h1.d = L * Thickness / deltax
h2D.d = deltay * Thickness / L
h2.l = h2D
h22.d = h1 / (h2D * 2)
y = y0 - ystep * deltay * h2 / deltax
x1_p_h2 = x1 + h2
x0_p_h2 = x0 + h2
x1_m_h2 = x1 - h2
For x = x0 - h2 To x1_p_h2
If ystep = 1
If x < x0_p_h2
h = 0
Else
h = h1
EndIf
If x > x1_m_h2
h3 = 0
Else
h3 = h1
EndIf
Else
If x < x0_p_h2
h3 = 0
Else
h3 = h1
EndIf
If x > x1_m_h2
h = 0
Else
h = h1
EndIf
EndIf
If steep
LineXY(y - h, x, y + h3, x, Color)
Else
LineXY(x, y - h, x, y + h3, Color)
EndIf
error - deltay
If error <= 0
y + ystep
error + deltax
EndIf
Next
EndIf
EndProcedure
EndModule
;{ exemple
CompilerIf #PB_Compiler_IsMainFile
#WD_main = 0
#GD_canvas = 0
Structure Canvas
IS_LeftButton.i
IS_ButtonDown.i
LastX.i
LastY.i
EndStructure
Procedure EventDraw()
Protected x.i = GetGadgetAttribute(#GD_canvas, #PB_Canvas_MouseX)
Protected y.i = GetGadgetAttribute(#GD_canvas, #PB_Canvas_MouseY)
Static r = 20, This.Canvas
Static Mode = 0
Draw = #False
With This
Select EventType()
Case #PB_EventType_KeyUp
If GetGadgetAttribute(#GD_canvas, #PB_Canvas_Key) = #PB_Shortcut_W
mode = 0
ElseIf GetGadgetAttribute(#GD_canvas, #PB_Canvas_Key) = #PB_Shortcut_B
mode = 1
Else
StartDrawing(CanvasOutput(#GD_canvas))
Box(0, 0, OutputWidth(), OutputHeight(), $ffffff)
StopDrawing()
EndIf
Case #PB_EventType_MouseWheel
r + GetGadgetAttribute(#GD_canvas, #PB_Canvas_WheelDelta) * 1
If r < 0 : r = 0 : EndIf
If r > 200 : r = 200 : EndIf
Case #PB_EventType_LeftButtonDown
\IS_ButtonDown = #True
\IS_LeftButton = #True
\LastX = x
\LastY = y
Draw = #True
Case #PB_EventType_LeftButtonUp
\IS_ButtonDown = #False
\IS_LeftButton = #True
Case #PB_EventType_RightButtonDown
\IS_ButtonDown = #True
\IS_LeftButton = #False
\lastX = x
\lastY = y
Draw = #True
Case #PB_EventType_RightButtonUp
\IS_ButtonDown = #False
\IS_LeftButton = #False
Case #PB_EventType_MouseMove
If \IS_ButtonDown
Draw = #True
EndIf
EndSelect
If Draw
If And StartDrawing(CanvasOutput(#GD_canvas))
Protected color.l = $000000
If \IS_LeftButton = #False
color = $ff0000
EndIf
;{ vitesse
;
; t = 100
;
; DisableDebugger
; time = ElapsedMilliseconds()
; For i = 0 To t
; Draw::WideLine(100, 100, 500, 200, r, color)
; Next
; time = ElapsedMilliseconds() - time
;
; time1 = ElapsedMilliseconds()
; For i = 0 To t
; Draw::BresenhamLine(100, 300, 500, 400, r, color)
; Next
; time1 = ElapsedMilliseconds() - time1
; EnableDebugger
;
; Debug " rayon = " + r + " : " + time + " - " + time1 + " -> " + StrD(time1 / time, 2)
;
;}
If mode = 0
Draw::WideLine(\lastX, \lastY, x, y, r, Color)
DrawText(0, 0, "[W/B] : MODE = WideLine ")
Else
Draw::BresenhamLine(\lastX, \lastY, x, y, r, Color)
DrawText(0, 0, "[W/B] : MODE = BresenhamLine")
EndIf
\lastX = x
\lastY = y
StopDrawing()
EndIf
EndIf
EndWith
EndProcedure
OpenWindow(#WD_main, 0, 0, 1024, 768, "Canvas Draw", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
CanvasGadget(#GD_canvas, 0, 0, 1024, 768, #PB_Canvas_Keyboard)
BindGadgetEvent(#GD_canvas, @EventDraw())
SetActiveGadget(#GD_canvas)
Repeat : Until WaitWindowEvent(10) = #PB_Event_CloseWindow
CompilerEndIf
;}
détails sur la comparaison en vitesse des 2 fonctions :
thickness = 0 :
idem (puisque = lineXY() )
thickness < 20 :
WideLine() est plus rapide que BresenhamLine()
thickness >= 20 & thickness < 100
BresenhamLine() est plus rapide que WideLine()
thickness >= 100
il semble que WideLine() soit à nouveau plus rapide.