IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Mathématiques Discussion :

Le bout d'une barbe ou comment dessiner une flèche


Sujet :

Mathématiques

  1. #21
    Membre averti
    Profil pro
    professeur des universités à la retraite
    Inscrit en
    Août 2008
    Messages
    364
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : professeur des universités à la retraite

    Informations forums :
    Inscription : Août 2008
    Messages : 364
    Points : 439
    Points
    439
    Par défaut
    Je reviens faire un tour... Je me suis servi de la réponse exposée dans le message précédent pour une solution à l'exercice 8 du Chapitre 13 du même ouvrage de Stroustrup:

    Define a class Hexagon. Use the center and the distance from the center to a corner point in constructor argument.
    Ce n'est peut-être pas la façon la plus élégante de construire un hexagone, mais j'ai trouvé cela amusant... et cela montre qu'on peut réutiliser la fonction barbs_ends() dans divers contextes.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
     
    const double Pi = 3.14159;
     
    class Hexagon : public Shape {
      public:
          Hexagon(Point cc, int rr);
          Hexagon(Point cc, int rr, double angle);
          Point center() { return c; }
          void set_center(Point cc) { c = cc;}
     
          void draw_lines() const;
     
          int radius() { return r;}
          void set_radius(int rr) { r = rr; } 
      private:
        Point c; //centre
        int r; // rayon
     
        vector<int> barbs_ends(const Point& A, const Point& B, const int& d, const double& Alpha) const;
    };
     
    //----------------------------------------------------------------------------
     
    Hexagon::Hexagon(Point cc, int rr, double alpha)
    : c(cc), r(rr)
    {
    // cc = centre; rr = rayon; alpha = angle en radians du diamètre contenant les sommets point1 et point4 (et bien sûr le centre point0) avec l'horizontale
     
      if ( r <= 0 ) error("Hexagon: rayon doit être (strictement) positif");
     
      // point0 = centre de l'hexagone
      Point point0(c.x,c.y);
     
      // les sommets point1, point2, point3... point6 se succèdent dans l'ordre inverse des aiguilles d'une montre
     
      // point1
      Point point1(c.x-r*cos(alpha),c.y+r*sin(alpha));
     
      vector<int> v;
      v = barbs_ends(point0, point1, r, Pi/3);
      //v[0],v[1] = coordonnées du sommet point2 (barbe gauche du segment point0-point1)
      //v[2], v[3] = coordonnées du sommet point6 (barbe de droite du segment point0-point1)
     
     
      Point point2(v[0],v[1]);
      Point point6(v[2], v[3]);
     
      Point point4(point0.x+r*cos(alpha),point0.y-r*sin(alpha)); // point diamétralement opposé à point1
    		      // point1 - point0 - point4 appariennent à un même diamètre faisant un angle alpha avec l'horizontale
     
      v = barbs_ends(point0, point4, r, Pi/3);
      //v[0],v[1] = coordonnées du sommet point5 (barbe gauche du segment point0 - point4)
      //v[2], v[3] = coordonnées du sommet point3 (barbe droite du segment point0 - point4)
     
      Point point3(v[2],v[3]);
      Point point5(v[0],v[1]);
     
      add(point0);add(point1);add(point2);add(point3);add(point4);add(point5);add(point6);
    }
     
    //----------------------------------------------------------------------------
     
    vector<int> Hexagon::barbs_ends(const Point& A, const Point& B, const int& d, const double& Alpha) const
    {
      // A = queue de la flèche, B = pointe de la flèche
      // d = longueur de chaque barbe
      // Alpha = angle de chaque barbe avec le corps de la flèche, en radians
     
      // la fonction renvoie un vecteur contenant les coordonnées x,y de M1 (v[0],v[1])
      // et de M2 ((v[2],v[3])
      // BM1 = barbe gauche (en regardant la pointe depuis la queue)
      // BM2 = barbe droite (en regardant la pointe depuis la queue)
     
      // Norme = distance AB
      double Norme = sqrt( pow(A.x-B.x,2) + pow(A.y-B.y,2) );
     
     
      double M1_x, M1_y, M2_x, M2_y; // coordonnées des extrémités M1 et M2 des deux barbes
     
     
      double Ix = (A.x-B.x)/Norme;
      double Iy = (A.y-B.y)/Norme;
      double Jx = Iy;
      double Jy = -1*Ix;
      double Dx = d*cos(Alpha);
      double Dy = d*sin(Alpha);
     
      M1_x = B.x + Dx*Ix - Dy*Jx;
      M1_y = B.y + Dx*Iy - Dy*Jy;
      M2_x = B.x + Dx*Ix + Dy*Jx;
      M2_y = B.y + Dx*Iy + Dy*Jy;
     
      vector<int> ends;  // pour les coordonnées des extrémités M1 et M2 des deux barbes
          ends.push_back(int(M1_x));
          ends.push_back(int(M1_y));
          ends.push_back(int(M2_x));
          ends.push_back(int(M2_y));
     
      return ends;
    }
     
    //----------------------------------------------------------------------------
     
    void Hexagon::draw_lines() const
    {
      // point(1) à point(6) : les points se suivent dans le sens inverse des aiguilles d'une montre
     
      if (color().visibility()) {
        fl_line(point(0).x, point(0).y, point(1).x,point(1).y); // rayon entre centre et point(1)
        fl_line(point(1).x, point(1).y, point(2).x,point(2).y);
        fl_line(point(2).x, point(2).y, point(3).x,point(3).y);
        fl_line(point(3).x, point(3).y, point(4).x,point(4).y);
        fl_line(point(4).x, point(4).y, point(5).x,point(5).y);
        fl_line(point(5).x, point(5).y, point(6).x,point(6).y);
        fl_line(point(6).x, point(6).y, point(1).x,point(1).y);
      }
    }
     
    //----------------------------------------------------------------------------
     
    int main()
    {
     
      Simple_window win(Point(0,0), 1650, 970, "Arrow");
     
      Hexagon hex(Point(150,150),80,0);
      Hexagon hex2(Point(150+160,150),80,Pi/3);
      Hexagon hex3(Point(150+160+160,150),80,Pi/6);
      Hexagon hex4(Point(150+160+160+160,150),80,Pi/12);
      Hexagon hex5(Point(150+160+160+160+160,150),80,-Pi/12);
      Hexagon hex6(Point(150+160+160+160+160+160,150),80,-Pi/12+Pi);
     
      win.attach(hex);
      win.attach(hex2);
      win.attach(hex3);
      win.attach(hex4);
      win.attach(hex5);
      win.attach(hex6);
      win.wait_for_button();
    }

  2. #22
    Membre averti
    Profil pro
    professeur des universités à la retraite
    Inscrit en
    Août 2008
    Messages
    364
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : professeur des universités à la retraite

    Informations forums :
    Inscription : Août 2008
    Messages : 364
    Points : 439
    Points
    439
    Par défaut
    Et voici une nouvelle implémentation de la classe Hexagon, que j'espère sensiblement moins maladroite que la précédente, et qui sera apparemment plus facile à généraliser à n'importe quel polygone régulier.
    L'implémentation recourt encore à la fonction barbs_ends() qui faisait l'objet de ce fil.

    J'utilise cette fois le Vector_ref de Stroustrup, défini dans le fichier Graph.h (disponible sur la Toile à http://www.stroustrup.com/Programming/Graphics/ ).

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    //----------------------------------------------------------------------------
     
    class Hexagon : public Shape {
      public:
          Hexagon(Point cc, int rr);
          Hexagon(Point cc, int rr, double angle);
          Point center() { return c; }
          void set_center(Point cc) { c = cc;}
     
          void draw_lines() const;
     
          int radius() { return r;}
          void set_radius(int rr) { r = rr; } 
      private:
        Point c; //centre
        int r; // rayon
     
        vector<int> barbs_ends(const Point& A, const Point& B, const int& d, const double& Alpha) const;
    };
     
    //----------------------------------------------------------------------------
     
    Hexagon::Hexagon(Point cc, int rr, double alpha)
    : c(cc), r(rr)
    {
      // cc = centre; rr = rayon; alpha = angle en radians du diamètre contenant le sommet 1 avec l'horizontale
     
      // les sommets 1, 2, 3... 6 se succèdent dans l'ordre inverse des aiguilles d'une montre
     
      if ( r <= 0 ) error("Hexagon: rayon doit être (strictement) positif");
     
      Vector_ref<Point> points;
     
      // centre de l'hexagone (placé en points[0])
      points.push_back(new Point(c.x,c.y));
     
      // sommet 1, placé en points[1]; points[0]-points[1] fait un angle alpha avec l'horizontale
      points.push_back(new Point(c.x-r*cos(alpha),c.y+r*sin(alpha)));
     
      vector<int> v;
      for (int i = 1; i < 6; ++i) {
        v = barbs_ends(points[0], points[i], r, Pi/3);
        //v[0],v[1] = coordonnées du sommet i+1 (barbe gauche du segment points[0]-points[i])
        points.push_back(new Point(v[0],v[1]));
      }
     
      for (int i = 0; i < points.size() ; ++i)
          add(points[i]);
    }
     
    //----------------------------------------------------------------------------
     
    vector<int> Hexagon::barbs_ends(const Point& A, const Point& B, const int& d, const double& Alpha) const
    {
      // A = queue de la flèche, B = pointe de la flèche
      // d = longueur de chaque barbe
      // Alpha = angle de chaque barbe avec le corps de la flèche, en radians
     
      // la fonction renvoie un vecteur contenant les coordonnées x,y de M1 (v[0],v[1])
      // et de M2 ((v[2],v[3])
      // BM1 = barbe gauche (en regardant la pointe depuis la queue)
      // BM2 = barbe droite (en regardant la pointe depuis la queue)
     
      // Norme = distance AB
      double Norme = sqrt( pow(A.x-B.x,2) + pow(A.y-B.y,2) );
     
     
      double M1_x, M1_y, M2_x, M2_y; // coordonnées des extrémités M1 et M2 des deux barbes
     
     
      double Ix = (A.x-B.x)/Norme;
      double Iy = (A.y-B.y)/Norme;
      double Jx = Iy;
      double Jy = -1*Ix;
      double Dx = d*cos(Alpha);
      double Dy = d*sin(Alpha);
     
      M1_x = B.x + Dx*Ix - Dy*Jx;
      M1_y = B.y + Dx*Iy - Dy*Jy;
      M2_x = B.x + Dx*Ix + Dy*Jx;
      M2_y = B.y + Dx*Iy + Dy*Jy;
     
      vector<int> ends;  // pour les coordonnées des extrémités M1 et M2 des deux barbes
          ends.push_back(int(M1_x));
          ends.push_back(int(M1_y));
          ends.push_back(int(M2_x));
          ends.push_back(int(M2_y));
     
      return ends;
    }
     
    //----------------------------------------------------------------------------
     
    void Hexagon::draw_lines() const
    {
      // point(0) = le centre de l'hexagone
      // point(1) = le premier point construit, le segment point(0)-point(1) fait un angle alpha avec l'horizontale
      // point(1) à point(6) : les sommets de l'hexagone, qui se suivent dans le sens inverse des aiguilles d'une montre
     
      if (color().visibility()) {
        fl_line(point(0).x, point(0).y, point(1).x,point(1).y); // rayon entre centre et point(1)
        fl_line(point(1).x, point(1).y, point(2).x,point(2).y);
        fl_line(point(2).x, point(2).y, point(3).x,point(3).y);
        fl_line(point(3).x, point(3).y, point(4).x,point(4).y);
        fl_line(point(4).x, point(4).y, point(5).x,point(5).y);
        fl_line(point(5).x, point(5).y, point(6).x,point(6).y);
        fl_line(point(6).x, point(6).y, point(1).x,point(1).y);
      }
    }
     
    //----------------------------------------------------------------------------
     
    int main()
    {
     
      Simple_window win(Point(0,0), 1650, 970, "Arrow");
     
      Hexagon hex(Point(150,150),80,0);
      Hexagon hex2(Point(150+160,150),80,Pi/3);
      Hexagon hex3(Point(150+160+160,150),80,Pi/6);
      Hexagon hex4(Point(150+160+160+160,150),80,Pi/12);
      Hexagon hex5(Point(150+160+160+160+160,150),80,-Pi/12);
      Hexagon hex6(Point(150+160+160+160+160+160,150),80,-Pi/12+Pi);
     
      win.attach(hex);
      win.attach(hex2);
      win.attach(hex3);
      win.attach(hex4);
      win.attach(hex5);
      win.attach(hex6);
     
      win.wait_for_button();
    }

  3. #23
    Membre averti
    Profil pro
    professeur des universités à la retraite
    Inscrit en
    Août 2008
    Messages
    364
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : professeur des universités à la retraite

    Informations forums :
    Inscription : Août 2008
    Messages : 364
    Points : 439
    Points
    439
    Par défaut
    Et tant qu'à faire, toujours avec barbs_ends(), voici une classe Regular_polygon, qui permet d'afficher un polygone régulier à n côtés, répondant ainsi à l'exercice 10 du Chapitre 13 de Stroustrup...

    Avec un très grand nombre de côtés il se passe des choses un peu désagréables, que je laisserai... de côté.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
     
    const double Pi = 3.14159265;
    //----------------------------------------------------------------------------
     
    class Regular_polygon : public Shape {
      public:
          Regular_polygon(Point cc, int rr, int nn);
          Regular_polygon(Point cc, int rr, double angle, int nn);
          Point center() { return c; }
          void set_center(Point cc) { c = cc;}
     
          void draw_lines() const;
     
          int radius() { return r;}
          void set_radius(int rr) { r = rr; } 
      private:
        Point c; //centre
        int r; // rayon
        int n; // nombre de côtés
     
        vector<int> barbs_ends(const Point& A, const Point& B, const int& d, const double& Alpha) const;
    };
     
    //----------------------------------------------------------------------------
     
    Regular_polygon::Regular_polygon(Point cc, int rr, double alpha, int nn)
    : c(cc), r(rr), n(nn)
    {
      // cc = centre; rr = rayon; alpha = angle en radians du rayon contenant le sommet 1 avec l'horizontale
      // nn = nb de côtés
     
      // les sommets 1, 2, 3... n se succèdent dans l'ordre inverse des aiguilles d'une montre
     
      if ( r <= 0 ) error("Regular_polygon: rayon doit être (strictement) positif");
      if ( n <= 2 ) error("Regular_polygon: nombre de côtés doit être supérieur à deux");
     
      Vector_ref<Point> points;
     
      // centre de l'hexagone (placé en points[0])
      points.push_back(new Point(c.x,c.y));
     
      // sommet 1, placé en points[1]; points[0]-points[1] fait un angle alpha avec l'horizontale
      points.push_back(new Point(c.x-r*cos(alpha),c.y+r*sin(alpha)));
     
      double longueur_cote = 2*r*sin(Pi/n);
      double angle_rayon_cote = (n - 2)*Pi/(2*n);
     
      vector<int> v;
      for (int i = 1; i < n; ++i) {
        v = barbs_ends(points[0], points[i], int(longueur_cote), angle_rayon_cote);
        //v[0],v[1] = coordonnées du sommet i+1 (barbe gauche du segment points[0]-points[i])
        points.push_back(new Point(v[0],v[1]));
     
      }
     
      for (int i = 0; i < points.size() ; ++i)
          add(points[i]);
    }
     
    //----------------------------------------------------------------------------
     
    vector<int> Regular_polygon::barbs_ends(const Point& A, const Point& B, const int& d, const double& Alpha) const
    {
      // A = queue de la flèche, B = pointe de la flèche
      // d = longueur de chaque barbe
      // Alpha = angle de chaque barbe avec le corps de la flèche, en radians
     
      // la fonction renvoie un vecteur contenant les coordonnées x,y de M1 (v[0],v[1])
      // et de M2 ((v[2],v[3])
      // BM1 = barbe gauche (en regardant la pointe depuis la queue)
      // BM2 = barbe droite (en regardant la pointe depuis la queue)
     
      // Norme = distance AB
      double Norme = sqrt( pow(A.x-B.x,2) + pow(A.y-B.y,2) );
     
     
      double M1_x, M1_y, M2_x, M2_y; // coordonnées des extrémités M1 et M2 des deux barbes
     
     
      double Ix = (A.x-B.x)/Norme;
      double Iy = (A.y-B.y)/Norme;
      double Jx = Iy;
      double Jy = -1*Ix;
      double Dx = d*cos(Alpha);
      double Dy = d*sin(Alpha);
     
      M1_x = B.x + Dx*Ix - Dy*Jx;
      M1_y = B.y + Dx*Iy - Dy*Jy;
      M2_x = B.x + Dx*Ix + Dy*Jx;
      M2_y = B.y + Dx*Iy + Dy*Jy;
     
      vector<int> ends;  // pour les coordonnées des extrémités M1 et M2 des deux barbes
          ends.push_back(int(M1_x));
          ends.push_back(int(M1_y));
          ends.push_back(int(M2_x));
          ends.push_back(int(M2_y));
     
      return ends;
    }
     
    //----------------------------------------------------------------------------
     
    void Regular_polygon::draw_lines() const
    {
      // point(0) = le centre de l'hexagone
      // point(1) = le premier point construit, le segment point(0)-point(1) fait un angle alpha avec l'horizontale
      // point(1) à point(6) : les sommets de l'hexagone, qui se suivent dans le sens inverse des aiguilles d'une montre
     
      // rayon entre centre et point(1) : utile pour déboguage
      fl_line(point(0).x, point(0).y, point(1).x,point(1).y);
     
      if (color().visibility()) {
          for (int i = 1; i < n; ++i)
    	    fl_line(point(i).x, point(i).y, point(i+1).x,point(i+1).y); // trace les côtés
     
          fl_line(point(n).x, point(n).y, point(1).x,point(1).y); // entre le dernier sommet et le premier
      }
    }
     
    //----------------------------------------------------------------------------
     
    int main()
    {
     
      Simple_window win(Point(0,0), 1650, 970, "Polygone régulier");
     
      Regular_polygon poly(Point(500,450),400,0, 11);
     
      win.attach(poly);
     
      win.wait_for_button();
    }

  4. #24
    Membre averti
    Profil pro
    professeur des universités à la retraite
    Inscrit en
    Août 2008
    Messages
    364
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : professeur des universités à la retraite

    Informations forums :
    Inscription : Août 2008
    Messages : 364
    Points : 439
    Points
    439
    Par défaut
    Au fond, les classes Arrow(), Hexagon(), Regular_polygon() proposées ci-dessus permettent à la fois de définir des types de forme ET de les positionner par rapport à une rotation. Dans une logique plus modulaire, ne serait-il pas plus élégant de définir ces classes de telle sorte qu'elles dessinent les objets graphiques dans une position par défaut usuelle et facile à calculer (flèche horizontale, polygone avec un sommet 1 sur un axe horizontal...) et de créer par ailleurs une fonction rotate(Shape& s, int n) (fugitivement suggérée par Stroustrup en 17.9.2) qui positionnerait n'importe quel objet d'une classe dérivée de Shape pour une rotation de n degrés (à supposer qu'une telle fonction puisse être réellement écrite...) ?

+ Répondre à la discussion
Cette discussion est résolue.
Page 2 sur 2 PremièrePremière 12

Discussions similaires

  1. Comment dessiner une fléche comme ceci ?
    Par jlassiramzy dans le forum AWT/Swing
    Réponses: 6
    Dernier message: 24/04/2007, 02h57
  2. Comment dessiner une flèche ?
    Par Amine_sas dans le forum 2D
    Réponses: 4
    Dernier message: 20/12/2006, 21h58
  3. Comment dessiner une petite interface de radar?
    Par jlassiramzy dans le forum AWT/Swing
    Réponses: 8
    Dernier message: 26/06/2006, 23h06
  4. Réponses: 3
    Dernier message: 29/06/2005, 14h29
  5. Comment dessiner une ligne dans un Chart ?
    Par libititi dans le forum Composants VCL
    Réponses: 3
    Dernier message: 16/06/2005, 14h56

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo