C'est une courbe d'équation x2/3 + y2/3 = k que décrit un point d'un cercle qui roule sans glisser à l'intérieur d'un cercle de rayon 4 fois plus grand. L'animation est lancée dès le démarrage : une nouvelle image est calculée toutes les 50ms.
Répertoire : astroide2. Trois fichiers : main.cpp, astroide.h et astroide.cpp.
#include <QApplication> #include "astroide.h" int main (int argc, char *argv []) { QApplication app (argc, argv); Fenetre f; f.show(); return app.exec (); }
On crée l'application app, le fenêtre principale f puis on lance la boucle d'exécution app.
#ifndef ASTROIDE_H #define ASTROIDE_H #include <QtGui> #include "geo2D/cercle.h" #include "geo2D/courbe.h" class fonction1: public fonction { public: bool def (double); double image (double x); };
Il faut deux fonctions car x2/3 + y2/3 = k équivaut à y = (k - x2/3)3/2 ou y = - (k - x2/3)3/2.
class Astroide: public QWidget { Q_OBJECT public: repere *R; pt *O, *M, *P; cercle *c, *c1; double angle; fonction *f; fonction1 *f1; courbe *cf, *cf1;
On déclare ici tous les objets géométriques qui seront utilisés.
bool deplace; Astroide (QWidget *parent = 0); protected: void paintEvent (QPaintEvent *); }; class Fenetre: public QWidget { Q_OBJECT public: QPushButton *bouton; Astroide *ast; Fenetre (QWidget *parent = 0); public slots: void action (); };
La fenêtre principale contient le bouton et la feuille de dessin ast.
/* * astroide2 * */ #include "astroide.h" bool fonction::def (double x) { return (x >= -4) && (x <= 4); } double fonction::image (double x) { if (x < 0.0) x = - x; return pow (2.5198420998 - pow (x, 0.6666666666666), 1.5); } bool fonction1::def (double x) { return fonction::def (x); } double fonction1::image (double x) { return - fonction::image (x); }
Définition de 2 fonctions : la première est f (x) = (k - x2/3)3/2et la seconde f1 (x) = - f(x).
Astroide::Astroide (QWidget *parent): QWidget (parent) { QTimer *timer = new QTimer (this); connect (timer, SIGNAL (timeout ()), this, SLOT (update ())); timer -> start (50);
On constuit un "timer" qui envoie un signal tous les 50 ms. A chaque "timeout" on redessine la figure. L'instruction connect relie chaque "timout" à la méthode update.
R = new repere (250, 250, 500, 500, 50.0, 50.0, 1.0, 1.0); O = new pt (0.0, 0.0, NULL, R); c = new cercle (O, 4, NULL, R); M = new pt (3.0, 0.0, "M", R); c1 = new cercle (M, 1, NULL, R); P = new pt (4, 0, "P", R); angle = 0.0; f = new fonction; cf = new courbe (f, NULL, R); f1 = new fonction1; cf1 = new courbe (f1, NULL, R);
On crée ici les objets géométriques.
setWindowTitle (QString::fromUtf8 ("L'Astroïde")); resize (500, 500); }
On donne un titre à la fenêtre, sans oublier le fromUtf8 à cause du ï puis on dimensionne la fenêtre.
void Astroide::paintEvent (QPaintEvent *) { if (angle == 0.0) { setPalette (QPalette (QColor (255, 255, 255))); setAutoFillBackground (true); } if (deplace) { angle += 0.02; M -> pt_x_y (3.0 * cos (angle), 3.0 * sin (angle)); c1 -> cercle_pt_r (M, 1); P -> pt_x_y (M -> x + cos (angle * 3), M -> y + sin (- angle * 3)); } QPainter painter (this); painter.setPen (Qt::red); R -> trace (&painter); painter.setPen (Qt::green); cf -> trace (&painter); cf1 -> trace (&painter); painter.setPen (Qt::blue); c -> trace (&painter); c1 -> trace (&painter); P -> trace (&painter); }
La première fois on peint le fond en blanc.
On ajoute 0.02 à l'angle que fait le petit cercle avec l'axe des abscisses puis on recalcule les coordonnées des points qui se sont déplacés.
Et enfin on redessine le tout.
void Fenetre::action () { if (ast -> deplace) { ast -> deplace = false; bouton -> setText ("Ok"); } else { ast -> deplace = true; bouton -> setText ("Stop"); } }
Un "clic" sur le bouton : onchange l'indicateur deplace puis le texte du bouton.
Fenetre::Fenetre (QWidget *parent): QWidget (parent) { bouton = new QPushButton ("Ok", this); bouton-> minimumSize (); connect (bouton, SIGNAL (clicked ()), this, SLOT (action ())); ast = new Astroide (parent); QVBoxLayout *vboite = new QVBoxLayout; vboite -> addWidget (bouton); vboite -> addWidget (ast); setLayout (vboite); setGeometry (0, 0, 550, 550); }
Constructeur de la fenêtre principale : on crée le bouton associé à la méthode action() puis la feuille de dessin. On dispose enfin ces deux objets verticalement dans la fenêtre.