Je vous propose aujourd’hui une application simple d’emploi, qui devrait ravir petit et grand, un Spirographe.

Il suffit d’ajuster les paramètres à l’aide de quelques curseurs et cases à cocher, de cliquer sur le bouton <Dessine> puis, d’ admirer le résultat.
Selon les paramètres sélectionnés, le tracé peut durer plusieurs minutes. Pour interrompre le tracé prématurément, un bouton <Stop> a été prévu.
Le curseur <Temporisation> peut être manipulé en cours de tracé afin de faire varier la vitesse de l'animation.
Exemple de dessin : Passe 1
Rayon roue fixe = 270
Rayon roue mobile = 20
Distance du crayon = 0
Pas de rotation = 5°
Angle de départ = 0°
Vitesse de déplacement R.M. = 80%
Temporisation , c’est vous qui voyez.
Roue mobile à l’intérieur = Coche
Inverser le sens = coche
Contour = coche
Couleur du contour = un Vert foncé
Animer le spirographe, c’est vous qui voyez.
Cliquez sur <Dessine>
Sans effacer, Paramètres suivants : Passe 2
Rayon roue fixe = 230
Rayon roue mobile = 50
Distance du crayon = 0
Pas de rotation = 7°
Angle de départ = 0°
Vitesse de déplacement R.M. = 60%
Temporisation , c’est vous qui voyez.
Roue mobile à l’intérieur = Coche
Inverser le sens = coche
Remplissage = coche
Couleur du remplissage = un bleu vif
Animer le spirographe, c’est vous qui voyez.
Cliquez sur <Dessine>
Sans effacer, Paramètres suivants : Passe 3
Rayon roue fixe = 125
Rayon roue mobile = 50
Distance du crayon = 0
Pas de rotation = 7°
Angle de départ = 0°
Vitesse de déplacement R.M. = 40%
Temporisation , c’est vous qui voyez.
Roue mobile à l’intérieur = Coche
Inverser le sens = décoche
Remplissage = coche
Couleur du remplissage = un rouge vif
Animer le spirographe, c’est vous qui voyez.
Cliquez sur <Dessine>
Sans effacer, Paramètres suivants : Passe 4
Rayon roue fixe = 20
Rayon roue mobile = 10
Distance du crayon = 0
Pas de rotation = 3°
Angle de départ = 0°
Vitesse de déplacement R.M. = 140%
Temporisation , c’est vous qui voyez.
Roue mobile à l’intérieur = Coche
Inverser le sens = décoche
Contour = coche
Couleur du remplissage = un violet
Animer le spirographe, c’est vous qui voyez.
Cliquez sur <Dessine>
Terminé.
Reste à sauvegarder en BMP pour imprimer.
Note : préférence de l'éditeur pour le source
Taille des tabulations = 2 |X| ASCII 9
Code : Tout sélectionner
; **********************************
; *** SpiroPat ***
; * Version : 20250215 *
; * PureBasic 6.20 pour windows *
;
;
Global .s Titre = "SpiroPat-V20250215."
Global .s FichierIni = GetCurrentDirectory() + "Spirographe.ini"
Global .s FichierBmp = GetCurrentDirectory() + ""
Global .s FichierSpr = GetCurrentDirectory() + ""
Global .i RayonMaxi = 300 / 5
Global .i RayonMini = 1
Global .i PasMini = 3
Global .i PasMaxi = 10
Global .i VitesseMaxi = 20
Global .i CouleurRemplissage = #Green
Global .i CouleurContour = #Black
Global .i Sens = 1
Global .i PositionRf = -1
Global .i Image_ArretUrgence
Global .i Image_CouleurRemplissage
Global .i Image_CouleurContour
Global .i LargeurButtonImage
Global .i HauteurButtonImage
Global .a TraceEnRun = #False
Global .a Passe
; **********************************
; *** Module Spirographe ***
; * Version : 20250215 *
; * PureBasic 6.20 pour windows *
;
DeclareModule Spirographe
; ******** Constantes et variables Publiques ***************
; ******** Declaration des procedures Publiques ***************
Declare Init ( _WinMere.i , _X.i , _Y.i , _Dimension.i )
Declare ExportBmp ( _NomFichier.s )
Declare ImportBmp ( _NomFichier.s )
Declare SetRayonFixe ( _Val.f )
Declare SetRayonMobile ( _Val.f )
Declare SetPas ( _Val.f )
Declare SetPositionCrayon ( _Val.f )
Declare SetVitesse ( _Val.f )
Declare SetPasse ( _Val.a )
Declare SetTempo ( _Val.i )
Declare SetVisu ( _Val.a )
Declare SetPenColor ( _Val.i )
Declare SetFillColor ( _Val.i )
Declare SetAngleDepart ( _Val.f )
Declare Cls ( )
Declare InitTrace ( )
Declare NextTrace ( )
Declare .a EndTrace ( )
EndDeclareModule
Module Spirographe
;{ ******** Constantes et variables privées ***************
Global _2Pi .f ; Constante
Global RayonRoueFixe .f ; Rayon du cercle fixe toujours positif RayonRoueFixe
Global RayonRoueMobile .f ; Rayon du cercle mobile :Positif vers l'exterieur ,negatif vers l'interieur RayonRoueMobile
Global Pas .f ; Pas de rotation du cercle mobile en radian toujour positif
Global PosCrayon .f ; Distance du crayon par rapport au bord du cercle mobile
Global Vitesse .f ; Vitesse de deplacement du cercle mobile sur le cercle fixe :Positif=sens direct ,negatif=sens inverse
Global AngleDepart .f ; Angle de départ pour le tracé en Radian
Global Rapport .f ; Pour calcul de position de la roue mobile sur la roue fixe
Global AngleRoueFixe .f
Global AngleRoueMobile .f
Global Passe .a ; 1 = Remplissage : 2 = Contour : 3 = les deux
Global Visu .a ; Affiche l'animation des roues
Global xRoueMobile .w
Global yRoueMobile .w
Global xCrayon .w
Global yCrayon .w
Global Axe .i ; Centrage du graphique
Global ImageDeFond .i
Global ImageEcran .i
Global SpriteEcran .i
Global Ecran .i
Global Dimension .i
Global PenColor .i ; Couleur contour
Global FillColor .i ; Couleur remplissage
Global Tempo .i ; Temporise l'affichage image par image en ms
Global Chrono .i ; Compteur
Global NbTourRoueFixe .f
Global NbTourRoueMobile .f
Global TourCompletRoueFixe .a
Global TourCompletRoueMobile .a
Global TraceComplet .a
Global RemplissageFini .a
Global ContourFini .a
Global PremierPoint .a
Global HoldxRoueMobile .w
Global HoldyRoueMobile .w
Global HoldxCrayon .w
Global HoldyCrayon .w
;}
; ******** Procedures Privées ***************
Procedure RestaureEcran ( ) ; Restaure ImageEcran avec ImageDeFond
If ImageEcran : FreeImage( ImageEcran ) : EndIf
ImageEcran = CopyImage( ImageDeFond, #PB_Any )
EndProcedure
Procedure CalculPositionSuivante ( )
; Calcule la prochaine position des roues
AngleRoueMobile = AngleRoueMobile + Pas ; Angle Roue mobile ; REVOIR LE CALCUL DES ANGLES
AngleRoueFixe = AngleRoueMobile * Rapport * Vitesse ; Angle sur la roue fixe de la position axe roue mobile
EndProcedure
Procedure CalculPositionRoues ( )
; Position roue mobile
xRoueMobile = Round( ( RayonRoueFixe + RayonRoueMobile ) * Cos( AngleRoueFixe + AngleDepart) , #PB_Round_Nearest )
yRoueMobile = -Round( ( RayonRoueFixe + RayonRoueMobile ) * Sin( AngleRoueFixe + AngleDepart) , #PB_Round_Nearest )
; Position du crayon
xCrayon = Round( ( RayonRoueMobile - PosCrayon ) * Cos( AngleRoueFixe + AngleRoueMobile + AngleDepart) , #PB_Round_Nearest )
yCrayon = -Round( ( RayonRoueMobile - PosCrayon ) * Sin( AngleRoueFixe + AngleRoueMobile + AngleDepart) , #PB_Round_Nearest )
EndProcedure
Procedure Frame ( ) ; Création du sprite avec ImageEcran et affiche à l'écran
StartDrawing (SpriteOutput( SpriteEcran ) )
DrawImage ( ImageID( ImageEcran) , 0 , 0 )
StopDrawing ( )
ClearScreen( #White )
DisplaySprite ( SpriteEcran , 0 , 0 )
FlipBuffers ( )
EndProcedure
Procedure AfficheRoue ( ) ; Dand l'image ecran
StartVectorDrawing ( ImageVectorOutput( ImageEcran ) )
AddPathCircle( Axe , Axe , RayonRoueFixe ) ; Place la roue fixe
VectorSourceColor( RGBA( 255 , 0 , 0 , 127 ) )
StrokePath( 4 )
AddPathCircle( Axe + xRoueMobile , Axe + yRoueMobile , Abs( RayonRoueMobile ) ) ; Place la roue mobile
VectorSourceColor( RGBA( 255 , 0 , 255 , 127 ) )
StrokePath( 4 )
MovePathCursor( Axe + xRoueMobile , Axe + yRoueMobile ) ; Place le crayon
AddPathLine( xCrayon , yCrayon , #PB_Path_Relative )
VectorSourceColor( RGBA( 255 , 0 , 255 , 127 ) )
StrokePath( 4 )
StopVectorDrawing()
EndProcedure
Procedure NextRemplissage ( )
CalculPositionRoues ( )
StartDrawing ( ImageOutput( ImageDeFond ) )
DrawingMode ( #PB_2DDrawing_Outlined )
LineXY ( Axe + xRoueMobile , Axe + yRoueMobile , Axe + xRoueMobile + xCrayon , Axe + yRoueMobile + yCrayon , FillColor )
CalculPositionSuivante ( )
If Abs( AngleRoueMobile ) > NbTourRoueMobile * _2Pi
TourCompletRoueMobile = #True
NbTourRoueMobile + 1
Else
TourCompletRoueMobile = #False
EndIf
If Abs( AngleRoueFixe ) > NbTourRoueFixe * _2Pi
TourCompletRoueFixe = #True
NbTourRoueFixe + 1
Else
TourCompletRoueFixe = #False
EndIf
If TourCompletRoueFixe And TourCompletRoueMobile
RemplissageFini = -1
AngleRoueMobile = 0
AngleRoueFixe = 0
CalculPositionRoues ( )
PremierPoint = #True
TourCompletRoueFixe = #False
TourCompletRoueMobile = #False
HoldxRoueMobile = 0
HoldyRoueMobile = 0
HoldxCrayon = 0
HoldyCrayon = 0
NbTourRoueFixe = 1
NbTourRoueMobile = 1
Else
EndIf
StopDrawing ( )
EndProcedure
Procedure NextContour ( )
StartDrawing ( ImageOutput( ImageDeFond ) )
DrawingMode ( #PB_2DDrawing_Outlined )
If PremierPoint ; Positionne le PremierPoint du tracé
CalculPositionRoues ( )
HoldxRoueMobile = xRoueMobile
HoldyRoueMobile = yRoueMobile
HoldxCrayon = xCrayon
HoldyCrayon = yCrayon
PremierPoint = #False
Else
CalculPositionSuivante ( )
If Abs( AngleRoueMobile ) > NbTourRoueMobile * _2Pi
TourCompletRoueMobile = #True
NbTourRoueMobile + 1
Else
TourCompletRoueMobile = #False
EndIf
If Abs( AngleRoueFixe ) > NbTourRoueFixe * _2Pi
TourCompletRoueFixe = #True
NbTourRoueFixe + 1
Else
TourCompletRoueFixe = #False
EndIf
If TourCompletRoueFixe And TourCompletRoueMobile
ContourFini = -1
AngleRoueMobile = 0
AngleRoueFixe = 0
CalculPositionRoues ( )
; Fermeture du tracé
LineXY ( Axe + HoldxRoueMobile + HoldxCrayon , Axe + HoldyRoueMobile + HoldyCrayon , Axe + xRoueMobile + xCrayon , Axe + yRoueMobile + yCrayon , PenColor )
PremierPoint = #True
TourCompletRoueFixe = #False
TourCompletRoueMobile = #False
HoldxRoueMobile = 0
HoldyRoueMobile = 0
HoldxCrayon = 0
HoldyCrayon = 0
NbTourRoueFixe = 1
NbTourRoueMobile = 1
Else
CalculPositionRoues ( )
LineXY ( Axe + HoldxRoueMobile + HoldxCrayon , Axe + HoldyRoueMobile + HoldyCrayon , Axe + xRoueMobile + xCrayon , Axe + yRoueMobile + yCrayon , PenColor )
HoldxRoueMobile = xRoueMobile
HoldyRoueMobile = yRoueMobile
HoldxCrayon = xCrayon
HoldyCrayon = yCrayon
EndIf
EndIf
StopDrawing ( )
EndProcedure
; ******** Procedures Publiques ************
Procedure SetRayonFixe ( _Val.f )
RayonRoueFixe = Abs( _Val )
Rapport = RayonRoueMobile / RayonRoueFixe
RestaureEcran ( ) ; Restaure ImageEcran avec ImageDeFond
CalculPositionRoues ( )
AfficheRoue ( ) ; Recadre les Roues en fonction des parametres
Frame ( )
EndProcedure
Procedure SetRayonMobile ( _Val.f )
RayonRoueMobile = _Val
Rapport = RayonRoueMobile / RayonRoueFixe
RestaureEcran ( ) ; Restaure ImageEcran avec ImageDeFond
CalculPositionRoues ( )
AfficheRoue ( ) ; Recadre les Roues en fonction des parametres
Frame ( )
EndProcedure
Procedure SetPas ( _Val.f )
Pas = Radian( _Val )
If RayonRoueMobile > RayonRoueFixe
Pas = - Pas
EndIf
EndProcedure
Procedure SetPositionCrayon ( _Val.f )
PosCrayon = Abs( Int( _Val ) )
If RayonRoueMobile < 0 : PosCrayon = -PosCrayon : EndIf
RestaureEcran ( ) ; Restaure ImageEcran avec ImageDeFond
CalculPositionRoues ( )
AfficheRoue ( ) ; Recadre les Roues en fonction des parametres
Frame ( )
EndProcedure
Procedure SetVitesse ( _Val.f )
Vitesse = _Val
If Vitesse = 0
Vitesse = 0.1
EndIf
EndProcedure
Procedure SetPasse ( _Val.a )
Passe = _Val
If Passe < 1
Passe = 1
EndIf
If Passe > 3
Passe = 3
EndIf
EndProcedure
Procedure SetTempo ( _Val.i ) ; En millisecondes
Tempo = Abs( _Val ) ; Temporise l'affichage image par image en ms
EndProcedure
Procedure SetVisu ( _Val.a )
Visu = _Val
EndProcedure
Procedure SetPenColor ( _Val.i )
PenColor = _Val
EndProcedure
Procedure SetFillColor ( _Val.i )
FillColor = _Val
EndProcedure
Procedure SetAngleDepart ( _Val.f ) ; En degrés
AngleDepart = Radian( _Val )
RestaureEcran ( ) ; Restaure ImageEcran avec ImageDeFond
CalculPositionRoues ( )
AfficheRoue ( ) ; Recadre les Roues en fonction des parametres
Frame ( )
EndProcedure
Procedure Cls ( )
StartDrawing ( ImageOutput( ImageDeFond ) )
Box ( 0 , 0 , Dimension , Dimension , #White )
StopDrawing ( )
RestaureEcran ( ) ; Restaure ImageEcran avec ImageDeFond
AfficheRoue ( ) ; Recadre les Roues en fonction des parametres
Frame ( )
EndProcedure
Procedure ExportBmp ( _NomFichier.s )
SaveImage ( ImageDeFond , _NomFichier , #PB_ImagePlugin_BMP )
EndProcedure
Procedure ImportBmp ( _NomFichier.s )
If ImageDeFond : FreeImage( ImageDeFond ) : EndIf
If ImageEcran : FreeImage( ImageEcran ) : EndIf
ImageDeFond = LoadImage( #PB_Any , _NomFichier )
ImageEcran = CopyImage( ImageDeFond, #PB_Any )
AfficheRoue ( ) ; Recadre les Roues en fonction des parametres
Frame ( )
EndProcedure
Procedure Init ( _WinMere.i , _X.i , _Y.i , _Dimension.i )
Protected .i OldGadgetList
Dimension = _Dimension
OldGadgetList = UseGadgetList ( WindowID( _WinMere ) )
InitSprite()
Ecran = OpenWindowedScreen ( WindowID( _WinMere ) , _X , _Y , Dimension , Dimension )
ImageDeFond = CreateImage ( #PB_Any , Dimension , Dimension , 24 , #White )
ImageEcran = CreateImage ( #PB_Any , Dimension , Dimension , 24 , #White )
SpriteEcran = CreateSprite ( #PB_Any , Dimension , Dimension )
UseGadgetList ( OldGadgetList )
RayonRoueFixe = 0.0 ; Rayon du cercle fixe toujour positif RayonRoueFixe
RayonRoueMobile = 0.0 ; Rayon du cercle mobile :Positif vers l'exterieur ,negatif vers l'interieur RayonRoueMobile
Pas = 0.0 ; Pas de rotation du cercle mobile en radian toujours positif
PosCrayon = 0.0 ; Distance du crayon par rapport au bord du cercle mobile toujours positif
Vitesse = 0.0 ; Vitesse de deplacement du cercle mobile sur le cercle fixe :Positif=sens direct ,negatif=sens inverse
Passe = 3 ; 1 = Remplissage : 2 = Contour : 3 = les deux
Tempo = 100 ; Temporise l'affichage image par image en ms
Visu = #True ; Affiche l'animation des roues
PenColor = RGB( 1 , 1 , 1 ) ; Couleur contour
FillColor = RGB( 0 , 255 , 0 ) ; Couleur remplissage
_2Pi = 2.0 * #PI ; Constante
Axe = Int( Dimension / 2 ) ; Centrage du graphique
RayonRoueFixe = 100
RayonRoueMobile = 50
Pas = Radian( 3 )
If RayonRoueMobile > RayonRoueFixe
Pas = - Pas
EndIf
PosCrayon = 10
If RayonRoueMobile < 0 : PosCrayon = -PosCrayon : EndIf
Vitesse = 1
AngleDepart = Radian( 0 )
Rapport = RayonRoueMobile / RayonRoueFixe
RestaureEcran ( ) ; Restaure ImageEcran avec ImageDeFond
AfficheRoue ( ) ; Recadre les Roues en fonction des parametres
Frame ( )
EndProcedure
Procedure InitTrace ( )
PremierPoint = #True
TourCompletRoueFixe = #False
TourCompletRoueMobile = #False
HoldxRoueMobile = 0
HoldyRoueMobile = 0
HoldxCrayon = 0
HoldyCrayon = 0
NbTourRoueFixe = 1
NbTourRoueMobile = 1
AngleRoueFixe = 0
AngleRoueMobile = 0
TraceComplet = 0
RemplissageFini = 0
ContourFini = 0
EndProcedure
Procedure NextTrace ( )
; Dessinne le graphe
If Not TraceComplet
If Passe & 1 ; Remplissage
If Not RemplissageFini : NextRemplissage ( ) : EndIf
Else
RemplissageFini = -1
EndIf
If Passe & 2 ; Contour
If RemplissageFini And Not ContourFini : NextContour ( ) : EndIf
Else
ContourFini = -1
EndIf
If RemplissageFini And ContourFini : TraceComplet = -1 : EndIf
RestaureEcran ( )
If Visu
AfficheRoue ( ) ; Recadre les Roues en fonction des parametres
While ElapsedMilliseconds() < Chrono : Wend
Chrono = ElapsedMilliseconds() + Tempo ; Temporisation
EndIf
Frame ( )
EndIf
EndProcedure
Procedure .a EndTrace ( )
ProcedureReturn TraceComplet
EndProcedure
; ******* Initialisation *******
EndModule
; *****************
; Le formulaire
Global Win_0
Global Frame_Parametre, Text_RFixe, String_RFixe, TrackBar_RFixe, Text_RMobile, String_RMobile, TrackBar_RMobile, Text_Crayon, String_Crayon, TrackBar_Crayon, Text_Pas, String_Pas, TrackBar_Pas, Text_AngleDepart, String_AngleDepart, TrackBar_AngleDepart, Text_Vitesse, String_Vitesse, TrackBar_Vitesse, Text_VitesseGenerale, String_VitesseGenerale, TrackBar_VitesseGenerale, Checkbox_RmInterieure, Checkbox_Sens, Frame_Trace, Option_Remplissage, Option_Contour, Option_Tout, ButtonImage_CouleurRemplissage, ButtonImage_CouleurContour, Checkbox_Animation, ButtonImage_ArretUrgence, Frame_Menu, Button_Dessine, Button_Efface, Button_ChargeBmp, Button_SauveBmp, Button_Quitter, Button_ChargeParametres, Button_SauveParametres, Frame_Infos, Editor_Infos
Declare BoutonOnClick(EventType)
Declare Checkbox_RmOnClick(EventType)
Declare TrackBarOnScroll(EventType)
Procedure OpenWin_0(x = 0, y = 0, width = 1040, height = 620)
Win_0 = OpenWindow(#PB_Any, x, y, width, height, "", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_ScreenCentered)
Frame_Parametre = FrameGadget(#PB_Any, 10, 10, 410, 200, "Paramètres")
Text_RFixe = TextGadget(#PB_Any, 20, 30, 140, 20, "Rayon roue fixe")
String_RFixe = StringGadget(#PB_Any, 160, 30, 50, 20, "", #PB_String_Numeric | #PB_String_ReadOnly)
TrackBar_RFixe = TrackBarGadget(#PB_Any, 220, 30, 190, 20, 0, 0)
Text_RMobile = TextGadget(#PB_Any, 20, 50, 140, 20, "Rayon roue mobile")
String_RMobile = StringGadget(#PB_Any, 160, 50, 50, 20, "", #PB_String_Numeric | #PB_String_ReadOnly)
TrackBar_RMobile = TrackBarGadget(#PB_Any, 220, 50, 190, 20, 0, 0)
Text_Crayon = TextGadget(#PB_Any, 20, 70, 140, 20, "Distance crayon")
String_Crayon = StringGadget(#PB_Any, 160, 70, 50, 20, "", #PB_String_Numeric | #PB_String_ReadOnly)
TrackBar_Crayon = TrackBarGadget(#PB_Any, 220, 70, 190, 20, 0, 0)
GadgetToolTip(TrackBar_Crayon, "Distance qui sépare la pointe du crayon du bord de la roue mobile.")
Text_Pas = TextGadget(#PB_Any, 20, 90, 140, 20, "Pas de rotation")
String_Pas = StringGadget(#PB_Any, 160, 90, 50, 20, "", #PB_String_Numeric | #PB_String_ReadOnly)
TrackBar_Pas = TrackBarGadget(#PB_Any, 220, 90, 190, 20, 0, 0)
GadgetToolTip(TrackBar_Pas, "Vitesse angulaire de la roue mobile en degrés par cycle.")
Text_AngleDepart = TextGadget(#PB_Any, 20, 110, 140, 20, "Angle de départ")
String_AngleDepart = StringGadget(#PB_Any, 160, 110, 50, 20, "", #PB_String_Numeric | #PB_String_ReadOnly)
TrackBar_AngleDepart = TrackBarGadget(#PB_Any, 220, 110, 190, 20, 0, 0)
GadgetToolTip(TrackBar_AngleDepart, "Angle de départ du tracé par pas de 15°.")
Text_Vitesse = TextGadget(#PB_Any, 20, 130, 140, 20, "Vitesse déplacement R.M.")
String_Vitesse = StringGadget(#PB_Any, 160, 130, 50, 20, "", #PB_String_Numeric | #PB_String_ReadOnly)
TrackBar_Vitesse = TrackBarGadget(#PB_Any, 220, 130, 190, 20, 0, 0)
GadgetToolTip(TrackBar_Vitesse, "Vitesse de déplacement de la roue mobile autour la roue fixe.")
Text_VitesseGenerale = TextGadget(#PB_Any, 20, 150, 140, 20, "Temporisation")
String_VitesseGenerale = StringGadget(#PB_Any, 160, 150, 50, 20, "", #PB_String_Numeric | #PB_String_ReadOnly)
TrackBar_VitesseGenerale = TrackBarGadget(#PB_Any, 220, 150, 190, 20, 0, 0)
GadgetToolTip(TrackBar_VitesseGenerale, "Ralenti l'affichage du tracé.")
Checkbox_RmInterieure = CheckBoxGadget(#PB_Any, 20, 180, 190, 20, "Roue mobile à l' interieure")
Checkbox_Sens = CheckBoxGadget(#PB_Any, 220, 180, 190, 20, "Inverser le sens")
GadgetToolTip(Checkbox_Sens, "Inverse le sens de rotation de la roue mobile.")
Frame_Trace = FrameGadget(#PB_Any, 10, 210, 410, 90, "Paramètres de traçage")
Option_Remplissage = OptionGadget(#PB_Any, 20, 230, 130, 20, "Remplissage")
Option_Contour = OptionGadget(#PB_Any, 20, 250, 130, 20, "Contour")
Option_Tout = OptionGadget(#PB_Any, 20, 270, 130, 20, "Les deux")
ButtonImage_CouleurRemplissage = ButtonImageGadget(#PB_Any, 160, 230, 50, 20, 0)
ButtonImage_CouleurContour = ButtonImageGadget(#PB_Any, 160, 250, 50, 20, 0)
Checkbox_Animation = CheckBoxGadget(#PB_Any, 220, 240, 190, 20, "Animer le spirographe")
ButtonImage_ArretUrgence = ButtonImageGadget(#PB_Any, 370, 260, 32, 32, 0)
Frame_Menu = FrameGadget(#PB_Any, 10, 300, 410, 110, "Menu")
Button_Dessine = ButtonGadget(#PB_Any, 20, 320, 110, 20, "Dessine")
Button_Efface = ButtonGadget(#PB_Any, 20, 350, 110, 20, "Efface")
Button_ChargeBmp = ButtonGadget(#PB_Any, 160, 320, 110, 20, "Charge BMP")
Button_SauveBmp = ButtonGadget(#PB_Any, 160, 350, 110, 20, "Sauve BMP")
Button_Quitter = ButtonGadget(#PB_Any, 160, 380, 110, 20, "Quitter")
Button_ChargeParametres = ButtonGadget(#PB_Any, 300, 320, 110, 20, "Charge Paramètres")
Button_SauveParametres = ButtonGadget(#PB_Any, 300, 350, 110, 20, "Sauve Paramètres")
Frame_Infos = FrameGadget(#PB_Any, 10, 410, 410, 190, "Infos")
Editor_Infos = EditorGadget(#PB_Any, 20, 430, 390, 170, #PB_Editor_ReadOnly | #PB_Editor_WordWrap)
EndProcedure
Procedure Win_0_Events(event)
Select event
Case #PB_Event_CloseWindow
ProcedureReturn #False
Case #PB_Event_Gadget
Select EventGadget()
Case TrackBar_RFixe
TrackBarOnScroll(EventType())
Case TrackBar_RMobile
TrackBarOnScroll(EventType())
Case TrackBar_Crayon
TrackBarOnScroll(EventType())
Case TrackBar_Pas
TrackBarOnScroll(EventType())
Case TrackBar_AngleDepart
TrackBarOnScroll(EventType())
Case TrackBar_Vitesse
TrackBarOnScroll(EventType())
Case TrackBar_VitesseGenerale
TrackBarOnScroll(EventType())
Case Checkbox_RmInterieure
Checkbox_RmOnClick(EventType())
Case ButtonImage_CouleurRemplissage
BoutonOnClick(EventType())
Case ButtonImage_CouleurContour
BoutonOnClick(EventType())
Case ButtonImage_ArretUrgence
BoutonOnClick(EventType())
Case Button_Dessine
BoutonOnClick(EventType())
Case Button_Efface
BoutonOnClick(EventType())
Case Button_ChargeBmp
BoutonOnClick(EventType())
Case Button_SauveBmp
BoutonOnClick(EventType())
Case Button_Quitter
BoutonOnClick(EventType())
Case Button_ChargeParametres
BoutonOnClick(EventType())
Case Button_SauveParametres
BoutonOnClick(EventType())
EndSelect
EndSelect
ProcedureReturn #True
EndProcedure
; *****************
;{ Initialisation de la fenêtre
OpenWin_0() ; ( width = 1040, height = 620 )
LargeurButtonImage = GadgetWidth ( ButtonImage_CouleurRemplissage )
HauteurButtonImage = GadgetHeight ( ButtonImage_CouleurRemplissage )
Image_CouleurRemplissage = CreateImage ( #PB_Any , LargeurButtonImage , HauteurButtonImage , 32 )
Image_CouleurContour = CreateImage ( #PB_Any , LargeurButtonImage , HauteurButtonImage , 32 )
; L'image du bouton STOP
Global Dim MesCouleurs .l ( 1 )
Restore Color_Bouton_Stop
Read .a N.a
ReDim MesCouleurs( N - 1 )
For I.a = 0 To N -1
Read .l MesCouleurs( I )
Next
Restore Data_Bouton_Stop
Read .a Larg.a
Read .a Haut.a
Global .i Image_Bouton_Stop = CreateImage( #PB_Any , Larg , Haut )
StartDrawing ( ImageOutput( Image_Bouton_Stop ) )
For Y.a = 0 To Haut - 1
For X.a = 0 To Larg - 1
Read .a C.a
Plot( X , Y , MesCouleurs( C ) )
Next
Next
StopDrawing()
SetWindowTitle ( Win_0 , Titre )
Texte$ = "Les dessins et les paramètres peuvent être sauvegardés sur dique pour être réutilisés par la suite. "
Texte$ + "On pourra aussi recharger un dessin afin de le compléter ou compléter le dessin en cours. " + Chr( 10 ) + Chr( 13 )
Texte$ + "Un bouton <STOP> permet d'interrompre le tracé à tout moment. " + Chr( 10 ) + Chr( 13 )
Texte$ + "Seul le curseur <Temporisation> peut être manipulé en cours de tracé afin de faire varier la vitesse de l'animation. "
ClearGadgetItems ( Editor_Infos )
SetGadgetItemText ( Editor_Infos , 0 , Texte$ )
SetGadgetAttribute( ButtonImage_ArretUrgence , #PB_Button_Image , ImageID( Image_Bouton_Stop ) )
;}
Procedure DesactiveBouton ( _Val.a )
DisableGadget( ButtonImage_CouleurRemplissage , _Val )
DisableGadget( ButtonImage_CouleurContour , _Val )
DisableGadget( Button_Dessine , _Val )
DisableGadget( Button_Efface , _Val )
DisableGadget( Button_SauveBmp , _Val )
DisableGadget( Button_ChargeBmp , _Val )
DisableGadget( Button_Quitter , _Val )
DisableGadget( Button_ChargeParametres , _Val )
DisableGadget( Button_SauveParametres , _Val )
DisableGadget( Checkbox_Animation , _Val )
DisableGadget( Checkbox_Sens , _Val )
DisableGadget( Checkbox_RmInterieure , _Val )
DisableGadget( Option_Remplissage , _Val )
DisableGadget( Option_Contour , _Val )
DisableGadget( Option_Tout , _Val )
DisableGadget( TrackBar_RFixe , _Val )
DisableGadget( TrackBar_RMobile , _Val )
DisableGadget( TrackBar_Crayon , _Val )
DisableGadget( TrackBar_Pas , _Val )
DisableGadget( TrackBar_Vitesse , _Val )
DisableGadget( TrackBar_AngleDepart , _Val )
EndProcedure
Procedure AfficheValeurs ( )
SetGadgetText ( String_RFixe , Str ( GetGadgetState ( TrackBar_RFixe ) * 5 ) )
SetGadgetText ( String_RMobile , Str ( GetGadgetState ( TrackBar_RMobile ) * 5 ) )
SetGadgetText ( String_Crayon , Str ( GetGadgetState ( TrackBar_Crayon ) ) )
SetGadgetText ( String_Pas , Str ( GetGadgetState ( TrackBar_Pas ) ) + "°" )
SetGadgetText ( String_Vitesse , Str ( GetGadgetState ( TrackBar_Vitesse ) * 10 ) + "%" )
SetGadgetText ( String_AngleDepart , Str ( GetGadgetState ( TrackBar_AngleDepart ) * 15 ) + "°" )
SetGadgetText ( String_VitesseGenerale, Str ( GetGadgetState ( TrackBar_VitesseGenerale) * 10 ) + "ms" )
EndProcedure
Procedure AfficheCouleur ( Image.i , Button.i , Couleur.i )
StartDrawing( ImageOutput( Image ) )
Box( 0 , 0 , LargeurButtonImage , HauteurButtonImage , Couleur )
StopDrawing()
SetGadgetAttribute( Button , #PB_Button_Image , ImageID( Image ) )
EndProcedure
Procedure ChargeParametresIni ( Fichier$ )
Protected .i ValTmp
OpenPreferences( Fichier$ )
PreferenceGroup("Parametre curseurs")
SetGadgetState ( TrackBar_RFixe , ReadPreferenceInteger ( "RFixe" , RayonMaxi / 2 ) )
SetGadgetState ( TrackBar_RMobile , ReadPreferenceInteger ( "RMobile" , RayonMaxi / 4 ) )
SetGadgetAttribute ( TrackBar_Crayon , #PB_TrackBar_Maximum , GetGadgetState( TrackBar_RMobile ) * 5 - 5 )
SetGadgetState ( TrackBar_Crayon , ReadPreferenceInteger ( "Crayon" , 0 ) )
SetGadgetState ( TrackBar_Pas , ReadPreferenceInteger ( "Pas" , PasMaxi / 2 ) )
SetGadgetState ( TrackBar_Vitesse , ReadPreferenceInteger ( "Vitesse" , VitesseMaxi / 2 ) )
SetGadgetState ( TrackBar_AngleDepart , ReadPreferenceInteger ( "Angle" , 0 ) )
PreferenceGroup("Parametre Roues")
If ReadPreferenceInteger ( "Sens" , 0 )
SetGadgetState( Checkbox_Sens , 1 )
Sens = -1
Else
SetGadgetState( Checkbox_Sens , 0 )
Sens = 1
EndIf
AfficheValeurs ( )
If ReadPreferenceInteger ( "Interieure" , 1 )
SetGadgetState( Checkbox_RmInterieure , 1 )
PositionRf = -1
Else
SetGadgetState( Checkbox_RmInterieure , 0 )
PositionRf = 1
EndIf
PreferenceGroup("Parametre Traçage")
ValTmp = ReadPreferenceInteger ( "Passe" , 3 )
If ValTmp = 1 : SetGadgetState( Option_Remplissage , 1 )
ElseIf ValTmp = 2 : SetGadgetState( Option_Contour , 1 )
ElseIf ValTmp = 3 : SetGadgetState( Option_Tout , 1 )
EndIf
CouleurRemplissage = ReadPreferenceInteger ( "Couleur Remplissage" , #Green )
AfficheCouleur ( Image_CouleurRemplissage , ButtonImage_CouleurRemplissage , CouleurRemplissage ) ;
CouleurContour = ReadPreferenceInteger ( "Couleur Contour" , #Black )
AfficheCouleur ( Image_CouleurContour , ButtonImage_CouleurContour , CouleurContour ) ;
ValTmp = ReadPreferenceInteger ( "Animation" , 1 )
If ValTmp = 1 : SetGadgetState( Checkbox_Animation , 1 )
Else : SetGadgetState( Checkbox_Animation , 0 )
EndIf
ClosePreferences()
EndProcedure
Procedure SauveParametresIni ( Fichier$ )
OpenPreferences( Fichier$ )
PreferenceGroup("Parametre curseurs")
WritePreferenceInteger ( "RFixe" , GetGadgetState ( TrackBar_RFixe ) )
WritePreferenceInteger ( "RMobile" , GetGadgetState ( TrackBar_RMobile ) )
WritePreferenceInteger ( "Crayon" , GetGadgetState ( TrackBar_Crayon ) )
WritePreferenceInteger ( "Pas" , GetGadgetState ( TrackBar_Pas ) )
WritePreferenceInteger ( "Vitesse" , GetGadgetState ( TrackBar_Vitesse ) )
WritePreferenceInteger ( "Angle" , GetGadgetState ( TrackBar_AngleDepart ) )
PreferenceGroup("Parametre Roues")
WritePreferenceInteger ( "Interieure" , GetGadgetState ( Checkbox_RmInterieure ) )
WritePreferenceInteger ( "Sens" , GetGadgetState ( Checkbox_Sens ) )
PreferenceGroup("Parametre Traçage")
If GetGadgetState( Option_Remplissage ) : WritePreferenceInteger ( "Passe" , 1 )
ElseIf GetGadgetState( Option_Contour ) : WritePreferenceInteger ( "Passe" , 2 )
ElseIf GetGadgetState( Option_Tout ) : WritePreferenceInteger ( "Passe" , 3 )
EndIf
WritePreferenceInteger ( "Couleur Remplissage" , CouleurRemplissage )
WritePreferenceInteger ( "Couleur Contour" , CouleurContour )
WritePreferenceInteger ( "Animation" , GetGadgetState ( Checkbox_Animation ) )
ClosePreferences()
EndProcedure
Procedure AfficheSpiro ( )
Spirographe::SetRayonFixe ( GetGadgetState ( TrackBar_RFixe ) * 5 )
Spirographe::SetRayonMobile ( GetGadgetState ( TrackBar_RMobile ) * 5 * PositionRf )
Spirographe::SetPositionCrayon ( GetGadgetState ( TrackBar_Crayon ) )
Spirographe::SetAngleDepart ( GetGadgetState ( TrackBar_AngleDepart ) * 15 )
EndProcedure
; Initialisation des boutons Image
AfficheCouleur ( Image_CouleurRemplissage , ButtonImage_CouleurRemplissage , CouleurRemplissage )
AfficheCouleur ( Image_CouleurContour , ButtonImage_CouleurContour , CouleurContour )
;{ Initialisation des gadgets
SetGadgetAttribute ( TrackBar_RFixe , #PB_TrackBar_Minimum , RayonMini )
SetGadgetAttribute ( TrackBar_RFixe , #PB_TrackBar_Maximum , RayonMaxi )
SetGadgetState ( TrackBar_RFixe , RayonMaxi / 2 )
SetGadgetAttribute ( TrackBar_RMobile , #PB_TrackBar_Minimum , RayonMini )
SetGadgetAttribute ( TrackBar_RMobile , #PB_TrackBar_Maximum , RayonMaxi )
SetGadgetState ( TrackBar_RMobile , RayonMaxi / 4 )
SetGadgetAttribute ( TrackBar_Crayon , #PB_TrackBar_Minimum , 0 )
SetGadgetAttribute ( TrackBar_Crayon , #PB_TrackBar_Maximum , GetGadgetState( TrackBar_RMobile ) - 5 )
SetGadgetState ( TrackBar_Crayon , GetGadgetState( TrackBar_RMobile ) )
SetGadgetAttribute ( TrackBar_Pas , #PB_TrackBar_Minimum , PasMini )
SetGadgetAttribute ( TrackBar_Pas , #PB_TrackBar_Maximum , PasMaxi )
SetGadgetState ( TrackBar_Pas , PasMaxi / 2 )
SetGadgetAttribute ( TrackBar_Vitesse , #PB_TrackBar_Minimum , 1 )
SetGadgetAttribute ( TrackBar_Vitesse , #PB_TrackBar_Maximum , VitesseMaxi )
SetGadgetState ( TrackBar_Vitesse , VitesseMaxi / 2 )
SetGadgetAttribute ( TrackBar_AngleDepart , #PB_TrackBar_Minimum , 0 )
SetGadgetAttribute ( TrackBar_AngleDepart , #PB_TrackBar_Maximum , 23 )
SetGadgetState ( TrackBar_AngleDepart , 0 )
SetGadgetAttribute ( TrackBar_VitesseGenerale , #PB_TrackBar_Minimum , 0 )
SetGadgetAttribute ( TrackBar_VitesseGenerale , #PB_TrackBar_Maximum , 20 )
SetGadgetState ( TrackBar_VitesseGenerale , 10 )
AfficheValeurs ( )
SetGadgetState ( Option_Tout , 1 )
SetGadgetState ( Checkbox_Animation , 1 )
SetGadgetState ( Checkbox_Sens , 0 )
SetGadgetState ( Checkbox_RmInterieure , 1 )
;}
; Zone de dessin : x = 430, y = 10, width = height = 600
Spirographe::Init ( Win_0 , 430 , 10 , 600 )
ChargeParametresIni ( FichierIni )
AfficheSpiro ( )
Spirographe::Cls ( )
; *****************
; Les procédures d'événements
Procedure BoutonOnClick (EventType)
DesactiveBouton ( #True )
Select EventGadget()
Case ButtonImage_CouleurRemplissage ;{
Couleur = ColorRequester()
If Couleur > -1
CouleurRemplissage = Couleur
AfficheCouleur ( Image_CouleurRemplissage , ButtonImage_CouleurRemplissage , CouleurRemplissage )
EndIf
;}
Case ButtonImage_CouleurContour ;{
Couleur = ColorRequester()
If Couleur > -1
CouleurContour = Couleur
AfficheCouleur ( Image_CouleurContour , ButtonImage_CouleurContour , CouleurContour )
EndIf
;}
Case Button_Dessine ;{
If GetGadgetState( Option_Remplissage ) : Passe = 1
ElseIf GetGadgetState( Option_Contour ) : Passe = 2
ElseIf GetGadgetState( Option_Tout ) : Passe = 3
EndIf
Spirographe::SetPasse ( Passe )
Spirographe::SetFillColor ( CouleurRemplissage )
Spirographe::SetPenColor ( CouleurContour )
If GetGadgetState( Checkbox_RmInterieure ) : PositionRf = -1
Else : PositionRf = 1
EndIf
If GetGadgetState( Checkbox_Sens ) : Sens = -1
Else : Sens = 1
EndIf
Spirographe::SetRayonFixe ( GetGadgetState ( TrackBar_RFixe ) * 5 )
Spirographe::SetRayonMobile ( GetGadgetState ( TrackBar_RMobile ) * 5 * PositionRf )
Spirographe::SetPositionCrayon ( GetGadgetState ( TrackBar_Crayon ) )
Spirographe::SetPas ( GetGadgetState ( TrackBar_Pas ) )
Spirographe::SetVitesse ( GetGadgetState ( TrackBar_Vitesse ) * 0.1 * Sens )
Spirographe::SetAngleDepart ( GetGadgetState ( TrackBar_AngleDepart ) * 15 )
If GetGadgetState( Checkbox_Animation )
Spirographe::SetVisu ( #True )
Spirographe::SetTempo( GetGadgetState( TrackBar_VitesseGenerale ) * 10 )
Else
Spirographe::SetVisu ( #False )
EndIf
Spirographe::InitTrace ( )
TraceEnRun = #True
;}
Case ButtonImage_ArretUrgence ;{
TraceEnRun = #False ; mettre fin au tracé
Spirographe::InitTrace ( )
Spirographe::SetRayonFixe( GetGadgetState ( TrackBar_RFixe ) * 5 )
;}
Case Button_Efface ;{
Spirographe::Cls ( )
;}
Case Button_SauveBmp ;{
FichierBmp = SaveFileRequester("Fichier à sauvegarder", FichierBmp, "BitMap (*.bmp)|*.bmp|Tous les fichiers (*.*)|*.*", 0 )
If FichierBmp And (FileSize(FichierBmp) = -1 Or MessageRequester("Fichier existant", "Ecraser celui-ci ? " + FichierBmp, #PB_MessageRequester_YesNo) = #PB_MessageRequester_Yes)
If GetExtensionPart( FichierBmp ) = "" : FichierBmp + ".bmp" : EndIf
Spirographe::ExportBmp ( FichierBmp )
EndIf
;}
Case Button_ChargeBmp ;{
FichierBmp = OpenFileRequester("Fichier à charger", FichierBmp, "BitMap (*.bmp)|*.bmp|Tous les fichiers (*.*)|*.*", 0 )
If FichierBmp
Spirographe::ImportBmp ( FichierBmp )
EndIf
;}
Case Button_Quitter ;{
SauveParametresIni ( FichierIni )
End
;}
Case Button_ChargeParametres ;{
FichierSpr = OpenFileRequester("Fichier à charger", FichierSpr, "Spiro (*.spr)|*.spr|Tous les fichiers (*.*)|*.*", 0 )
If FichierSpr
SetWindowTitle ( Win_0 , Titre + " | " + GetFilePart( FichierSpr ) )
ChargeParametresIni ( FichierSpr )
Spirographe::InitTrace ( )
AfficheSpiro ( )
EndIf
;}
Case Button_SauveParametres ;{
FichierSpr = SaveFileRequester("Fichier à sauvegarder", FichierSpr, "Spiro (*.spr)|*.spr|Tous les fichiers (*.*)|*.*", 0 )
If FichierSpr And (FileSize(FichierSpr) = -1 Or MessageRequester("Fichier existant", "Ecraser celui-ci ? " + FichierSpr, #PB_MessageRequester_YesNo) = #PB_MessageRequester_Yes)
If GetExtensionPart( FichierSpr ) = "" : FichierSpr + ".spr" : EndIf
SetWindowTitle ( Win_0 , Titre + " | " + GetFilePart( FichierSpr ) )
SauveParametresIni ( FichierSpr )
EndIf
;}
EndSelect
If Not TraceEnRun : DesactiveBouton ( #False ) : EndIf
EndProcedure
Procedure TrackBarOnScroll (EventType)
SetGadgetAttribute ( TrackBar_Crayon , #PB_TrackBar_Maximum , GetGadgetState( TrackBar_RMobile ) * 5 -5 )
AfficheValeurs ( )
Select EventGadget()
Case TrackBar_RFixe ;{
Spirographe::setRayonFixe ( GetGadgetState( TrackBar_RFixe ) * 5 )
;}
Case TrackBar_RMobile ;{
If GetGadgetState( Checkbox_RmInterieure )
PositionRf = -1
Else
PositionRf = 1
EndIf
Spirographe::SetRayonMobile ( GetGadgetState( TrackBar_RMobile ) * 5 * PositionRf )
Spirographe::SetPositionCrayon ( GetGadgetState( TrackBar_Crayon ) )
;}
Case TrackBar_Crayon ;{
Spirographe::SetPositionCrayon ( GetGadgetState( TrackBar_Crayon ) )
;}
Case TrackBar_AngleDepart ;{
Spirographe::SetAngleDepart ( GetGadgetState( TrackBar_AngleDepart ) * 15 )
;}
Case TrackBar_VitesseGenerale ;{
Spirographe::SetTempo( GetGadgetState( TrackBar_VitesseGenerale ) * 10 )
;}
EndSelect
EndProcedure
Procedure Checkbox_RmOnClick (EventType)
Select EventGadget()
Case Checkbox_RmInterieure ;{
If GetGadgetState( Checkbox_RmInterieure )
PositionRf = -1
Else
PositionRf = 1
EndIf
;}
EndSelect
Spirographe::SetRayonMobile ( GetGadgetState ( TrackBar_RMobile ) * 5 * PositionRf )
Spirographe::SetPositionCrayon ( GetGadgetState ( TrackBar_Crayon ) )
EndProcedure
; *****************
; La boucle principale
Repeat
; Le cycle peut durer plus d'une minute selon les paramètres
If TraceEnRun ; Le dessin est-il toujour en cours ?
If Spirographe::EndTrace() ; Si le cycle est términé
TraceEnRun = #False ; mettre fin au tracé
DesactiveBouton ( #False ) ; Réactiver les boutons
Spirographe::SetRayonFixe( GetGadgetState ( TrackBar_RFixe ) * 5 )
Else ; Sinon
Spirographe::NextTrace( ) ; on trace l'image suivante
EndIf
EndIf
; événementielle automtiquement générée pour la fenêtre.
Event = WindowEvent()
Select EventWindow()
Case Win_0 ;{
Win_0_Events(Event)
;}
EndSelect
Delay( 1 )
Until Event = #PB_Event_CloseWindow
DataSection
Color_Bouton_Stop:
Data .a 7
Data .l $00FFFFFF
Data .l $00000000
Data .l $00C0C0C0
Data .l $00808080
Data .l $00000080
Data .l $000000FF
Data .l $00800080
Data_Bouton_Stop:
Data .a 32 , 32
Data .a $00,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$00
Data .a $01,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$02,$01
Data .a $01,$00,$02,$02,$02,$02,$02,$02,$02,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$02,$02,$02,$02,$02,$02,$02,$02,$03,$01
Data .a $01,$00,$02,$02,$02,$02,$02,$02,$03,$03,$04,$04,$04,$04,$04,$04,$04,$04,$04,$04,$04,$04,$03,$02,$02,$02,$02,$02,$02,$02,$03,$01
Data .a $01,$00,$02,$02,$02,$02,$02,$03,$03,$04,$04,$04,$04,$04,$04,$04,$04,$04,$04,$04,$04,$04,$04,$03,$02,$02,$02,$02,$02,$02,$03,$01
Data .a $01,$00,$02,$02,$02,$02,$03,$03,$04,$04,$04,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$04,$03,$02,$02,$02,$02,$02,$03,$01
Data .a $01,$00,$02,$02,$02,$03,$03,$04,$04,$04,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$04,$03,$02,$02,$02,$02,$03,$01
Data .a $01,$00,$02,$02,$03,$03,$04,$04,$04,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$04,$03,$02,$02,$02,$03,$01
Data .a $01,$00,$02,$03,$03,$04,$04,$04,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$04,$03,$02,$02,$03,$01
Data .a $01,$00,$03,$03,$04,$04,$04,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$04,$03,$02,$03,$01
Data .a $01,$00,$03,$04,$04,$04,$05,$00,$00,$06,$05,$00,$00,$00,$00,$00,$06,$05,$00,$00,$06,$05,$05,$00,$00,$00,$06,$05,$04,$02,$03,$01
Data .a $01,$00,$03,$04,$04,$05,$00,$06,$06,$00,$06,$06,$06,$00,$06,$06,$06,$00,$06,$06,$00,$06,$05,$00,$06,$06,$00,$06,$05,$00,$03,$01
Data .a $01,$00,$03,$04,$04,$05,$00,$06,$05,$00,$06,$05,$05,$00,$06,$05,$05,$00,$06,$05,$00,$06,$05,$00,$06,$05,$00,$06,$05,$00,$03,$01
Data .a $01,$00,$03,$04,$04,$05,$00,$06,$05,$06,$06,$05,$05,$00,$06,$05,$05,$00,$06,$05,$00,$06,$05,$00,$06,$05,$00,$06,$05,$00,$03,$01
Data .a $01,$00,$03,$04,$04,$05,$00,$06,$05,$05,$05,$05,$05,$00,$06,$05,$05,$00,$06,$05,$00,$06,$05,$00,$06,$05,$00,$06,$05,$00,$03,$01
Data .a $01,$00,$03,$04,$04,$05,$06,$00,$00,$06,$05,$05,$05,$00,$06,$05,$05,$00,$06,$05,$00,$06,$05,$00,$00,$00,$06,$06,$05,$00,$03,$01
Data .a $01,$00,$03,$04,$04,$05,$05,$06,$06,$00,$06,$05,$05,$00,$06,$05,$05,$00,$06,$05,$00,$06,$05,$00,$06,$06,$06,$05,$05,$00,$03,$01
Data .a $01,$00,$03,$04,$04,$05,$05,$05,$05,$00,$06,$05,$05,$00,$06,$05,$05,$00,$06,$05,$00,$06,$05,$00,$06,$05,$05,$05,$05,$00,$03,$01
Data .a $01,$00,$03,$04,$04,$05,$00,$06,$05,$00,$06,$05,$05,$00,$06,$05,$05,$00,$06,$05,$00,$06,$05,$00,$06,$05,$05,$05,$05,$00,$03,$01
Data .a $01,$00,$03,$04,$04,$05,$00,$06,$05,$00,$06,$05,$05,$00,$06,$05,$05,$00,$06,$05,$00,$06,$05,$00,$06,$05,$05,$05,$05,$00,$03,$01
Data .a $01,$00,$03,$04,$04,$05,$00,$06,$05,$00,$06,$05,$05,$00,$06,$05,$05,$00,$06,$05,$00,$06,$05,$00,$06,$05,$05,$05,$05,$00,$03,$01
Data .a $01,$00,$03,$04,$04,$05,$06,$00,$00,$06,$06,$05,$05,$00,$06,$05,$05,$06,$00,$00,$06,$06,$05,$00,$06,$05,$05,$05,$05,$00,$03,$01
Data .a $01,$00,$02,$00,$04,$05,$05,$06,$06,$06,$05,$05,$05,$06,$06,$05,$05,$05,$06,$06,$06,$05,$05,$06,$06,$05,$05,$05,$00,$00,$03,$01
Data .a $01,$00,$02,$02,$00,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$00,$00,$02,$03,$01
Data .a $01,$00,$02,$02,$02,$00,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$00,$00,$02,$02,$03,$01
Data .a $01,$00,$02,$02,$02,$02,$00,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$00,$00,$02,$02,$02,$03,$01
Data .a $01,$00,$02,$02,$02,$02,$02,$00,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$00,$00,$02,$02,$02,$02,$03,$01
Data .a $01,$00,$02,$02,$02,$02,$02,$02,$00,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$00,$00,$02,$02,$02,$02,$02,$03,$01
Data .a $01,$00,$02,$02,$02,$02,$02,$02,$02,$00,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$00,$00,$02,$02,$02,$02,$02,$02,$03,$01
Data .a $01,$00,$02,$02,$02,$02,$02,$02,$02,$02,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$02,$02,$02,$02,$02,$02,$02,$03,$01
Data .a $01,$02,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$01
Data .a $00,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$00
EndDataSection