Intersection d'une droite et d'un cercle

Il s'agit ici d' un exemple d'intersection dune droite et d'un cercle. Si les points d'intersection n'existent pas l'indicateur defini de ces points et de tous les objets enfants recoivent la valeur FALSE. Ils ne seront pas représentés.

idc.png

Répertoire : idc. Trois fichiers : main.cpp, fenetre.h et fenetre.cpp.

main.cpp

#include <QApplication>

#include "fenetre.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.

fenetre.h

#ifndef FENETRE_H
#define FENETRE_H

#include <QWidget>
#include <QPaintEvent>
#include <QMouseEvent>
#include <QPainter>
#include "geo2D/point_libre.h"
#include "geo2D/droite.h"
#include "geo2D/cercle.h"
#include "geo2D/point.h"

On déclare les objets de la bibiliothèque Qt nécessaires. On peut écrire directement #include <QtGui>. Seuls les objets utiles seront annexés. On déclare ensuite les objets de la bibliothèque geo2D nécessaires.On peut écrire directement #include "geo2D/geo2D.h" mais dans ce cas tous les objets de la bibliothèque geo2Dseront ajoutés au programme qui sera donc plus gros.

class Fenetre: public QWidget {

    Q_OBJECT

public:
    repere *R;
    pt *O;
    point_libre *A;
    point_libre *B;
    droite *AB;
    cercle *c;
    point *M;
    point *N;

On déclare ici tous les objets géométriques qui seront utilisés.

    bool presse;

Indicateur signalant qu'il y a un déplacement en cours

    Fenetre (QWidget *parent = 0);

protected:
    void paintEvent (QPaintEvent *);
    void mousePressEvent(QMouseEvent *event);
    void mouseMoveEvent(QMouseEvent *event);
    void mouseReleaseEvent(QMouseEvent *event);

};

#endif

On définit ici les quatre fonctions gérant le dessin et l'action de la souris (appui sur le bouton, déplacement, relâchement).

fenetre.cpp

/*
 * idc
 *
 * intersection d'une droite et d'un cercle
 */

#include "fenetre.h"
#include 

Fenetre::Fenetre (QWidget *parent): QWidget (parent) {
    setGeometry (0, 0, 600, 450);
    setMouseTracking (true);
    setCursor (Qt::ArrowCursor);
    presse = false;

Constructeur de la fenêtre principale : on indique sa taille, on donne la possibilité de gérer le déplacement de la souris sans qu'on ait besoin d'appuyer sur le bouton (setMouseTracking (true);), on fixe le curseur par défaut puis on initialise l'indicateur de déplacement des points libres.

    R = new repere (300, 225, 600, 450, 50.0, 50.0, 1.0, 1.0);
    A = new point_libre (3.0, 2.0, "A", R);
    B = new point_libre (3.0, -2.0, "B", R);
    AB = new droite (A, B, NULL, R);
    O = new pt (0.0, 0.0, "O", R);
    c = new cercle (O, 2.0, NULL, R);
    M = new point ("M", R);
    N = new point ("N", R);
    M -> intersection1 (AB, c);
    N -> intersection2 (AB, c);
}

On crée ici les objets géométriques, le repère, les points A, B, le point fixe O, le cercle et les deux points d'intersection M et N.

void Fenetre::paintEvent (QPaintEvent *) {
    setPalette (QPalette (QColor (255, 255, 255)));
    setAutoFillBackground (true);
    QPainter painter (this);
    painter.setPen (Qt::red);
    R -> trace (&painter);
    O -> trace (&painter);
    painter.setPen (Qt::blue);
    A -> trace (&painter);
    B -> trace (&painter);
    AB -> trace (&painter);
    c -> trace (&painter);
    M -> trace (&painter);
    N -> trace (&painter);
}

On redessine ici la figure : on peint le fond en blanc, on trace le repère en rouge puis les points, la droite, le cercle et s'ils existent les points d'intersection M et N.

void Fenetre::mousePressEvent (QMouseEvent *event) {
    int X = event -> x ();
    int Y = event -> y ();
    presse = A -> select (X, Y) || B -> select (X, Y);
    if (presse)
        setCursor (Qt::ClosedHandCursor);
}

On teste, dans cet ordre, si la souris est proche de A ou de B. Si c'est le cas l'indicateur de déplacement du point est positionné ainsi que le booléen presse. On change ensuite le curseur.

void Fenetre::mouseMoveEvent (QMouseEvent *event) {
    int X = event -> x ();
    int Y = event -> y ();
    if (presse) {
        if (A -> bouge (X, Y) || B -> bouge (X, Y))
            AB -> droite_pt_pt (A, B);
        M -> intersection1 (AB, c);
        N -> intersection2 (AB, c);
        update ();

Si le déplacement d'un point est en cours (presse = TRUE) alors on modifie ses coordonnées à l'écran (méthode bouge (X, Y);). On recalcule ensuite la droite puis les coordonnées d'éventuels points d'intersection. On redessine enfin la figure (méthode update();). NB la méthode bouge (X, Y); n'agit que sur le point en cours de déplacement.

    } else {
        if (A -> zone (X, Y) || B -> zone (X, Y))
            setCursor (Qt::PointingHandCursor);
        else
            setCursor (Qt::ArrowCursor);
    }
}

Si on bouge la souris sans appuyer sur le bouton en change simplement le curseur à proximité de A ou B.

void Fenetre::mouseReleaseEvent (QMouseEvent *) {
    A -> stop();
    B -> stop();
    presse = false;
    setCursor (Qt::PointingHandCursor);
}

On relâche de bouton de la souris : on remet alors tous les indicateurs de déplacement à FALSE puis on change le curseur.