Voilà comme tout le monde en ce moment, j'ai un peu de temps pour coder. (fin pas tant que ça en faite)
Une connaissance m'a fait connaitre l'Algorithme de Bresenham. Bon je ne vais pas décrire ici dans le detail ce qu'est l'Algorithme de Bresenham. Wikipedia le fait tres bien. Ou un moteur de recherche quelconque. La toile ne manque a ce sujet et en français.
Si je dois résumé, ça permet de tracer une ligne entre 2 ponts. Du moins dans mon cas, car l'Algorithme a depuis était décliner pour toutes sortes de formes.
Je me suis donc dit : "tiens voilà un défi a essayer de relever". Forcément, si je post c'est que c'est réussi.
Même si j'en vois certain qui vont dire : "Ba il y a la fonction line() qui fait ça très bien". Tout a fait comme ci-dessous :
Code : Tout sélectionner
If OpenWindow(0, 0, 0, 200, 200, "Line", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
If CreateImage(0, 200, 200) And StartDrawing(ImageOutput(0))
Box(0, 0, 200, 200, RGB(255, 255, 255))
For Width = 1 To 180 Step 5
Line(10, 10, Width, 180, RGB(Random(255), Random(255), Random(255)))
Next Width
StopDrawing()
ImageGadget(0, 0, 0, 200, 200, ImageID(0))
EndIf
Repeat
Event = WaitWindowEvent()
Until Event = #PB_Event_CloseWindow
EndIf
Mais c'est avant tout pour ma culture personnelle, le plaisir de gratter un peut de code. Et aussi vous allez voir dans certain cas elle peut s’avérer utile. (même si aujourd'hui je n'en ai pas l'utilité)
Voici donc dans un premier temps, l'Algorithme de Bresenham seul qui a était réalisé:
Code : Tout sélectionner
Procedure Bresenham(x1, y1, x2, y2)
ex = Abs(x2-x1)
ey = Abs(y2-y1)
dx = 2*ex
dy = 2*ey
dxx = ex
dyy = ey
i = 0
xincr = 1
yincr = 1
If (x1>x2)
xincr = -1
EndIf
If (y1>y2)
yincr = -1
EndIf
;{ cas 1 Dx plus grand que Dy
If (dxx>dyy)
While i<=dxx
; on récupere les coordonnees via x1 et y1
Debug x1
Debug y1
i+1
x1+ xincr
ex - dy
If ex < 0
y1+yincr
ex+dx
EndIf
Wend
EndIf
;}
;{ cas 2 Dx plus petit que Dy
If (dxx<dyy)
While i<=dyy
; on récupere les coordonnees via x1 et y1
Debug x1
Debug y1
i+1
y1+ yincr
ey - dx
If ey < 0
x1+xincr
ey+dy
EndIf
Wend
EndIf
;}
;{ cas 3 Dx = Dy
If (dxx=dyy)
While i<=dyy
; on récupere les coordonnees via x1 et y1
Debug x1
Debug y1
i+1
y1+ yincr
ey - dx
If ey < 0
x1+xincr
ey+dy
EndIf
Wend
EndIf
;}
EndProcedure
Voici donc un code qui montre le fonctionnement dans un tableau.
Pour utilisé le code, tout ce fait a la souris.
Le bouton gauche affiche le point de départ de la ligne. Le bouton droit affiche le point d'arrivé.
Code : Tout sélectionner
; //////////////////////////////////////////////////
; // Autor : Venom //
; // Project name : Algorithme de Bresenham //
; // Version : V 2.0 //
; // Compilator : PureBasic V5.72 //
; // Date : 29/03/2020 //
; // OS : Windows 10 //
; //////////////////////////////////////////////////
;- Window Constants
Enumeration
#Window_0
EndEnumeration
;- Gadgets Constants
Enumeration
#AffichageGrille
#AffichagePointDepart
#AffichagePointArriver
#AffichagePointTracer
EndEnumeration
Global TailleCarre = 10, LargeurTotal = 600, HauteurTotal = 600
Global NbCaseLargeur = LargeurTotal/TailleCarre, NbCaseHauteur = HauteurTotal/TailleCarre
Global x1 = 0, y1 = 0, x2 = 59, y2 = 59 ; positionnement au demarrage des points de depart et arriver
Global Dim Tableau(NbCaseLargeur, NbCaseHauteur)
; initialisations
InitSprite()
InitKeyboard()
InitMouse()
; declaration des procedures
Declare AffichageGrille()
Declare PointDepart()
Declare PointArriver()
Declare PointTracer()
Declare ViderTableau()
Declare Bresenham(x1, y1, x2, y2)
;==================================================================================================
;==================================================================================================
; OUVERTURE DE LA FENETRE
;==================================================================================================
;==================================================================================================
If OpenWindow(#Window_0, 0, 0, 600, 600, "Algorithme de Bresenham", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_TitleBar | #PB_Window_ScreenCentered)
OpenWindowedScreen(WindowID(#Window_0), 0, 0, 600, 600)
; on charge les differents sprites
AffichageGrille()
PointDepart()
PointArriver()
PointTracer()
EndIf
;==================================================================================================
;==================================================================================================
; BOUCLES
;==================================================================================================
;==================================================================================================
Repeat
Repeat
Event = WindowEvent()
Select Event
Case #PB_Event_CloseWindow
End
EndSelect
Until Event = 0
ExamineMouse()
; creer et affiche le curseur de la souris
If StartDrawing(ScreenOutput())
DrawingMode(#PB_2DDrawing_Transparent)
DrawText(MouseX(), MouseY(), Chr(42), RGB(255,0,255))
StopDrawing()
EndIf
; on appui sur le bouton gauche de la souris qui correspond au point de depart (vert)
If MouseButton(#PB_MouseButton_Left) <> 0
x1 = MouseX()/TailleCarre
y1 = MouseY()/TailleCarre
EndIf
; on appui sur le bouton droit de la souris qui correspond au point d'arriver (rouge)
If MouseButton(#PB_MouseButton_Right) <> 0
x2 = MouseX()/TailleCarre
y2 = MouseY()/TailleCarre
EndIf
FlipBuffers()
ClearScreen(RGB(0, 0, 0))
; on affiche la grille de fond
DisplaySprite(#AffichageGrille, 0, 0)
; on appel la procedure qui affiche le résultat du tracer
Bresenham(x1, y1, x2, y2)
; on affiche les ponts de depart et arriver sur le tracer
DisplaySprite(#AffichagePointDepart, x1*TailleCarre, y1*TailleCarre)
DisplaySprite(#AffichagePointArriver, x2*TailleCarre, y2*TailleCarre)
ExamineKeyboard()
Until KeyboardPushed(#PB_Key_Escape)
End
;==================================================================================================
;==================================================================================================
; PROCEDURES
;==================================================================================================
;==================================================================================================
Procedure AffichageGrille()
CreateSprite(#AffichageGrille, LargeurTotal, HauteurTotal)
If StartDrawing(SpriteOutput(#AffichageGrille))
For x = 0 To 800 Step 0
x+TailleCarre
Line(x, 0, 1, 800, $303030) ; ligne verticale
Line(0, x, 800, 1, $303030) ; ligne horizontale
Next
StopDrawing()
EndIf
EndProcedure
Procedure PointDepart()
CreateSprite(#AffichagePointDepart, TailleCarre, TailleCarre)
If StartDrawing(SpriteOutput(#AffichagePointDepart))
Box(0, 0, TailleCarre, TailleCarre, #Green)
StopDrawing()
EndIf
Tableau(x1, y1) = 1
EndProcedure
Procedure PointArriver()
CreateSprite(#AffichagePointArriver, TailleCarre, TailleCarre)
If StartDrawing(SpriteOutput(#AffichagePointArriver))
Box(0, 0, TailleCarre, TailleCarre, #Red)
StopDrawing()
EndIf
Tableau(x2, y2) = 2
EndProcedure
Procedure PointTracer()
CreateSprite(#AffichagePointTracer, TailleCarre, TailleCarre)
If StartDrawing(SpriteOutput(#AffichagePointTracer))
Box(0, 0, TailleCarre, TailleCarre, #Yellow)
StopDrawing()
EndIf
EndProcedure
Procedure ViderTableau()
For tx = 0 To NbCaseLargeur-1
For ty = 0 To NbCaseHauteur-1
Tableau(tx, ty) = 0
Next
Next
EndProcedure
Procedure Bresenham(x1, y1, x2, y2)
; Debug "x1 -> " + x1
; Debug "y1 -> " + y1
; Debug "x2 -> " + x2
; Debug "y2 -> " + y2
; Debug "ex -> " + ex
; Debug "ey -> " + ey
; Debug "dx -> " + dx
; Debug "dy -> " + dy
; Debug "dxx -> " + dxx
; Debug "dyy -> " + dyy
; on vide le tableau pour afficher le nouveau tracer
ViderTableau()
; on commence les calculs pour le tracer
ex = Abs(x2-x1)
ey = Abs(y2-y1)
dx = 2*ex
dy = 2*ey
dxx = ex
dyy = ey
i = 0
xincr = 1
yincr = 1
If (x1>x2)
xincr = -1
EndIf
If (y1>y2)
yincr = -1
EndIf
;{ cas 1 Dx plus grand que Dy
If (dxx>dyy)
While i<=dxx
Tableau(x1, y1) = 3 ; on récupere les coordonnees du tracer pour les integrés au tableau ID 3
i+1
x1+ xincr
ex - dy
If ex < 0
y1+yincr
ex+dx
EndIf
Wend
EndIf
;}
;{ cas 2 Dx plus petit que Dy
If (dxx<dyy)
While i<=dyy
Tableau(x1, y1) = 3 ; on récupere les coordonnees du tracer pour les integrés au tableau ID 3
i+1
y1+ yincr
ey - dx
If ey < 0
x1+xincr
ey+dy
EndIf
Wend
EndIf
;}
;{ cas 3 Dx = Dy
If (dxx=dyy)
While i<=dyy
Tableau(x1, y1) = 3 ; on récupere les coordonnees du tracer pour les integrés au tableau ID 3
i+1
y1+ yincr
ey - dx
If ey < 0
x1+xincr
ey+dy
EndIf
Wend
EndIf
;}
; on affiche la grille du fond
DisplaySprite(#AffichageGrille, 0, 0)
; on affiche le tracer contenue dans le tableau ID 3
For tx = 0 To NbCaseLargeur-1
For ty = 0 To NbCaseHauteur-1
If Tableau(tx, ty) = 3 ; tracer
DisplaySprite(#AffichagePointTracer, tx*TailleCarre, ty*TailleCarre)
EndIf
Next
Next
EndProcedure
Ps : vous pouvez changez la dimension de la grille via le variable TailleCarre ligne 25
Ps² : j'ai suivi cette vidéo qui explique bien le déroulement.
@++