Courbe d'une fonction dépendant d'un paramètre

Il s'agit dans cet exemple de tracer la courbe de la fonction f (x) = m x2. C'est un curseur qui permet la récupération de la valeur du paramètre m.

fparm.png

fparm.cpp

/**
 * fparm.cpp
 *
 * fonction dépendant d'un paramètre
 */

#include "geo2D/geo2D.h"

#define W 800
#define H 600
#define W0 400
#define H0 300

class fcarre: public fonction {

public:
    double m;
    fcarre (double m);
    double image (double x);
};

fcarre est une sur-classe de la classe fonction.

fcarre::fcarre (double m) {
    fcarre::m = m;
}

bool fonction::def (double x) {
    return TRUE;
}

double fonction::image (double x) {
    return 0.0;
}

On définit les deux méthodes de la classe fonction.

double fcarre::image (double x) {
    return m * x * x;
}

Retourne l'image du réel x par la fonction carré qui dépend du paramètre m.

class Donnees {

public:
    GdkCursor *fleche;
    GdkCursor *hand;
    bool presse;

    repere *R;
    curseur *cm;
    fcarre *f;
    courbe *c;
};

On définit les données géométriques et les outils utiles dans cette application.

static void paint (GtkWidget *widget, GdkEventExpose *event, Donnees *D) {

    cairo_t *cr;
    cr = gdk_cairo_create (widget->window);                  // création du graphique
    cairo_select_font_face (cr, "Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
    cairo_set_font_size (cr, 12.0);                                 // on fixe la police et sa taille

    cairo_set_source_rgb (cr, 1,1,1);                             // on peint l'écran en blanc
    cairo_paint (cr);
    cairo_stroke (cr);

    cairo_set_source_rgb (cr, 1, 0, 0);
    cairo_set_line_width (cr, 1.0);
    D->R->trace (cr);

    cairo_set_source_rgb (cr, 0, 0, 1);
    cairo_set_line_width (cr, 1.0);
    D->cm->trace (cr);
    D->c->trace (cr);
    cairo_stroke (cr);
    cairo_destroy (cr);

}

On redessine ici le graphique.

static void event_press (GtkWidget *widget, GdkEventButton *event, Donnees *D) {
    int X = event->x;
    int Y = event->y;
    D->presse = D->cm->select (X, Y) || D->cm->select_curseur (X, Y);
    if (D->presse)
        gdk_window_set_cursor (widget->window, D->hand);
}

On gère ici l'appui sur le bouton gauche de la souris.

static void event_motion (GtkWidget *widget, GdkEventMotion *event, Donnees *D) {
    int X = event->x;
    int Y = event->y;
    if (D->presse) {
        D->cm->bouge (X, Y);
        D->cm->bouge_curseur (X, Y);
        D->f->m = D->cm->valeur ();
        gtk_widget_queue_draw (widget);
    } else
        gdk_window_set_cursor (widget->window, (D->cm->zone (X, Y) || D->cm->zone_curseur (X, Y)) ?
                                 D->hand : D->fleche);
}

On gère ici la déplacement de la souris.

static void event_release (GtkWidget *widget, GdkEventButton *event, Donnees *D) {
    D->cm->stop ();
    D->cm->stop_curseur ();
    D->presse = FALSE;
    gdk_window_set_cursor (widget->window, D->fleche);
}

On gère ici le relachement du bouton de la souris

int main (int argc, char *argv []) {
    GtkWidget *fenetre;
    Donnees *D;

    D = new Donnees;

    D->R = new repere (W0, H0, W, H, 50.0, 50.0, 1.0, 1.0);
    D-> cm = new curseur (-2.0, 2.0, 0.5, W - 300, 100, 200, "m", D->R);
    D->f = new fcarre (0.5);
    D->c = new courbe (D->f, NULL, D->R);
    D->presse = false;

    gtk_init (&argc, &argv);

    D->fleche = gdk_cursor_new (GDK_LEFT_PTR);
    D->hand = gdk_cursor_new (GDK_HAND1);

    fenetre = gtk_window_new (GTK_WINDOW_TOPLEVEL);

    g_signal_connect (fenetre, "expose-event", G_CALLBACK (paint), D);
    g_signal_connect (fenetre, "destroy", G_CALLBACK (gtk_main_quit), NULL);

    gtk_widget_add_events (fenetre, GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK
                                    | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK);
    g_signal_connect (G_OBJECT (fenetre), "button_press_event", G_CALLBACK (event_press), D);
    g_signal_connect (G_OBJECT (fenetre), "button_release_event", G_CALLBACK (event_release), D);
    g_signal_connect (G_OBJECT (fenetre), "motion_notify_event", G_CALLBACK (event_motion), D);

    gtk_window_set_position (GTK_WINDOW (fenetre), GTK_WIN_POS_CENTER);
    gtk_window_set_default_size (GTK_WINDOW (fenetre), W, H);
    gtk_widget_set_app_paintable (fenetre, TRUE);
    gtk_widget_show_all (fenetre);

    gtk_main ();

    return 0;
}

Programme principal (voir les commentaires concernant l'application droite.cpp).