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

Autres IDE Pascal Discussion :

Courbe représentative d'une fonction numérique


Sujet :

Autres IDE Pascal

  1. #1
    Rédacteur/Modérateur

    Avatar de Roland Chastain
    Homme Profil pro
    Enseignant
    Inscrit en
    Décembre 2011
    Messages
    4 072
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Décembre 2011
    Messages : 4 072
    Points : 15 462
    Points
    15 462
    Billets dans le blog
    9
    Par défaut Courbe représentative d'une fonction numérique
    Bonjour !

    Je vous propose un programme qui trace la courbe représentative d'une fonction numérique.

    Pour la fenêtre et le dessin, j'ai utilisé la librairie OWL, après m'être replongé dans le classique tutoriel d'Alcatîz.

    L'autre point intéressant, c'est le passage d'une fonction comme argument à une procédure. J'ai trouvé la solution en fouillant dans les exemples deTP7.

    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
    {************************************************}
    {                                                }
    { Procedural Types Demo                          }
    { Copyright (c) 1985,90 by Borland International }
    {                                                }
    {************************************************}
     
    {$F+}
    program ProcVar;
    { For an extensive discussion of procedural types, variables and
      parameters, refer to the Programmer's Guide.
    }
     
    type
      IntFuncType = function (x, y : integer) : integer; { No func. identifier }
     
    var
      IntFuncVar : IntFuncType;
    On peut donc déclarer autant de fonctions qu'on veut, et les passer à la procédure de dessin ; mais il faut les écrire dans le code.

    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
     
    (* Virtual Pascal 2.1 *)
     
    program Fonction;
    {&PMTYPE PM}
    (* Courbe représentative d'une fonction numérique *)
     
    uses Windows, OWindows, Couleurs;
     
    type
      tFonction = function(const x: single): single;
     
    function F(const x: single): single;
    begin
      F := 2 * Cos(x) * x;
    end;
     
    type
      pFenetre = ^tFenetre;
      tFenetre = object(tWindow)
        pinceauFond: hBrush;
        constructor Init(aParent: pWindowsObject; aTitle: pChar);
        procedure GetWindowClass(var aWndClass: tWndClass); virtual;
        procedure TraceCourbe(aDC: hDC; aFonction: tFonction; aCouleur: tColorRef);
        procedure Paint(paintDC: hDC; var paintInfo: tPaintStruct); virtual;
        procedure WMKeyDown(var aMsg: tMessage); virtual wm_First + wm_keyDown;
        procedure WMLButtonDown(var Msg : tMessage); virtual wm_First + wm_LButtonDown;
        destructor Done; virtual;
      end;
     
      tProgramme = object(tApplication)
        procedure InitMainWindow; virtual;
      end;
     
    constructor tFenetre.Init(aParent: pWindowsObject; aTitle: pChar);
    var
      i: LongInt;
    begin
      tWindow.Init(aParent, aTitle);
      attr.style := ws_Popup or ws_Visible;
      attr.x := (GetSystemMetrics(sm_CXScreen) - 512) div 2;
      attr.y := (GetSystemMetrics(sm_CYScreen) - 512) div 2;
      attr.w := 512;
      attr.h := 512;
      pinceauFond := CreateSolidBrush(DarkSlateGray);
    end;
     
    procedure tFenetre.GetWindowClass(var aWndClass: tWndClass);
    begin
      tWindow.GetWindowClass(aWndClass);
      aWndClass.hbrBackground := pinceauFond;
    end;
     
    procedure tFenetre.TraceCourbe(aDC: hDC; aFonction: tFonction; aCouleur: tColorRef);
    var
      x, y: single;
      xEcran, yEcran: longInt;
    begin
      x := -7.0;
      while x < +7.0 do
      begin
    ////////////////////////////////////////////////////////////////////////////////
        y := aFonction(x);
    ////////////////////////////////////////////////////////////////////////////////
        if Abs(y) < 7.0 then
        begin
          xEcran := Round(+32 * x + 256);
          yEcran := Round(-32 * y + 256);
          SetPixel(aDC, xEcran, yEcran, aCouleur);
        end;
    ////////////////////////////////////////////////////////////////////////////////
        x := x + 0.02;
    ////////////////////////////////////////////////////////////////////////////////
      end;
    end;
     
    procedure tFenetre.Paint(paintDC: hDC; var paintInfo: tPaintStruct);
    var
      ancienCrayon, crayon : hPen;
    begin
    //////////////////////////////////////////////////////////////////////////////// 
      crayon := CreatePen(ps_Solid, 1, FernGreen);
      ancienCrayon := SelectObject(paintDC, crayon);
    ////////////////////////////////////////////////////////////////////////////////
      MoveTo(paintDC, 256,  32);
      LineTo(paintDC, 256, 480);
      MoveTo(paintDC,  32, 256);
      LineTo(paintDC, 480, 256);
      MoveTo(paintDC, 254, 224);
      LineTo(paintDC, 259, 224);
      MoveTo(paintDC, 288, 254);
      LineTo(paintDC, 288, 259);
    ////////////////////////////////////////////////////////////////////////////////
      SelectObject(paintDC, ancienCrayon);
      DeleteObject(crayon);
    ////////////////////////////////////////////////////////////////////////////////
      TraceCourbe(paintDC, F, WhiteSmoke);
    ////////////////////////////////////////////////////////////////////////////////
    end;
     
    procedure tFenetre.WMKeyDown (var aMsg: tMessage);
    begin
      CloseWindow;
    end;
     
    procedure tFenetre.WMLButtonDown (var Msg : tMessage);
    begin
      CloseWindow;
    end;
     
    destructor tFenetre.Done;
    begin
      DeleteObject(pinceauFond);
      tWindow.Done;
    end;
     
    procedure tProgramme.InitMainWindow;
    begin
      MainWindow := New(pFenetre, Init(nil, 'Fonction'));
    end;
     
    var
      prog: tProgramme;
     
    begin
      prog.Init('fonction');
      prog.Run;
      prog.Done;
    end.
    Après m'être battu un bon moment avec les différentes options de la procédure GetSystemMetrics (pour essayer de trouver les dimensions de la fenêtre à partir des dimensions du rectangle "client"), j'ai opté pour la fenêtre sans bordure ni barre de titre : là c'est tombé tout de suite juste.
    Images attachées Images attachées  
    Fichiers attachés Fichiers attachés
    Mon site personnel consacré à MSEide+MSEgui : msegui.net

  2. #2
    Responsable Pascal, Lazarus et Assembleur


    Avatar de Alcatîz
    Homme Profil pro
    Ressources humaines
    Inscrit en
    Mars 2003
    Messages
    7 937
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 57
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ressources humaines
    Secteur : Service public

    Informations forums :
    Inscription : Mars 2003
    Messages : 7 937
    Points : 59 415
    Points
    59 415
    Billets dans le blog
    2
    Par défaut
    Bonjour et
    Citation Envoyé par Roland Chastain Voir le message
    Après m'être battu un bon moment avec les différentes options de la procédure GetSystemMetrics (pour essayer de trouver les dimensions de la fenêtre à partir des dimensions du rectangle "client"), j'ai opté pour la fenêtre sans bordure ni barre de titre : là c'est tombé tout de suite juste.
    Quel était le style initial de la fenêtre ?
    Règles du forum
    Cours et tutoriels Pascal, Delphi, Lazarus et Assembleur
    Avant de poser une question, consultez les FAQ Pascal, Delphi, Lazarus et Assembleur
    Mes tutoriels et sources Pascal

    Le problème en ce bas monde est que les imbéciles sont sûrs d'eux et fiers comme des coqs de basse cour, alors que les gens intelligents sont emplis de doute. [Bertrand Russell]
    La tolérance atteindra un tel niveau que les personnes intelligentes seront interdites de toute réflexion afin de ne pas offenser les imbéciles. [Fiodor Mikhaïlovitch Dostoïevski]

  3. #3
    Rédacteur/Modérateur

    Avatar de Roland Chastain
    Homme Profil pro
    Enseignant
    Inscrit en
    Décembre 2011
    Messages
    4 072
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Décembre 2011
    Messages : 4 072
    Points : 15 462
    Points
    15 462
    Billets dans le blog
    9
    Par défaut
    Citation Envoyé par Alcatîz Voir le message
    Quel était le style initial de la fenêtre ?
    Au départ, je n'avais pas renseigné le champ style.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    constructor tFenetre.Init(aParent: pWindowsObject; aTitle: pChar);
    var
      i: LongInt;
    begin
      tWindow.Init(aParent, aTitle);
      //attr.style := ws_Popup or ws_Visible;
    Mon site personnel consacré à MSEide+MSEgui : msegui.net

  4. #4
    Rédacteur/Modérateur

    Avatar de Roland Chastain
    Homme Profil pro
    Enseignant
    Inscrit en
    Décembre 2011
    Messages
    4 072
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Décembre 2011
    Messages : 4 072
    Points : 15 462
    Points
    15 462
    Billets dans le blog
    9
    Par défaut
    J'ai trouvé un style de fenêtre qui me conviendrait : avec une barre de titre et un bouton "fermer", mais non-redimensionnable.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
      attr.style := ws_Overlapped or ws_Caption or ws_SysMenu;
    Je n'ai pas encore cherché la solution : j'ai ajouté de grandes marges pour mettre en évidence le problème.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
      attr.w := LARGEUR + 50;
      attr.h := HAUTEUR + 50;
    Fichiers attachés Fichiers attachés
    Mon site personnel consacré à MSEide+MSEgui : msegui.net

  5. #5
    Rédacteur/Modérateur

    Avatar de Roland Chastain
    Homme Profil pro
    Enseignant
    Inscrit en
    Décembre 2011
    Messages
    4 072
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Décembre 2011
    Messages : 4 072
    Points : 15 462
    Points
    15 462
    Billets dans le blog
    9
    Par défaut
    Voilà, j'ai trouvé et je crois avoir compris une erreur que je faisais. C'est qu'en haut il n'y a pas de border, n'est-ce pas ? Je veux dire qu'il n'y a rien entre le rectangle client et la barre de titre, de sorte qu'il faut ajouter deux fois le bord en largeur, mais une seule fois en hauteur. Enfin, c'est ce que je crois comprendre.

    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
    constructor tFenetre.Init(aParent: pWindowsObject; aTitle: pChar);
    var
      i: longInt;
    begin
      tWindow.Init(aParent, aTitle);
      attr.style := ws_Overlapped or ws_Caption or ws_SysMenu;
     
      attr.w := LARGEUR + 2 * GetSystemMetrics(sm_CXBorder);
      attr.h := HAUTEUR + 1 * GetSystemMetrics(sm_CYBorder) + GetSystemMetrics(sm_CYCaption);
     
      attr.x := (GetSystemMetrics(sm_CXScreen)-attr.w) div 2;
      attr.y := (GetSystemMetrics(sm_CYScreen)-attr.h) div 2;
     
      pinceauFond := CreateSolidBrush(MidnightBlue);
    end;
    Maintenant, avec une fenêtre "retaillable", ce serait un autre problème.
    Fichiers attachés Fichiers attachés
    Mon site personnel consacré à MSEide+MSEgui : msegui.net

  6. #6
    Responsable Pascal, Lazarus et Assembleur


    Avatar de Alcatîz
    Homme Profil pro
    Ressources humaines
    Inscrit en
    Mars 2003
    Messages
    7 937
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 57
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ressources humaines
    Secteur : Service public

    Informations forums :
    Inscription : Mars 2003
    Messages : 7 937
    Points : 59 415
    Points
    59 415
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par Roland Chastain Voir le message
    Maintenant, avec une fenêtre "retaillable", ce serait un autre problème.
    Étant donné que la méthode Paint redessine la fenêtre à chaque fois qu'elle est invalidée, la fonction GetClientRect peut te retourner à tout moment la taille de la zone client ; il y a peu de modifications à faire au programme pour que tous les calculs de coordonnées se fassent relativement à cette taille.
    Règles du forum
    Cours et tutoriels Pascal, Delphi, Lazarus et Assembleur
    Avant de poser une question, consultez les FAQ Pascal, Delphi, Lazarus et Assembleur
    Mes tutoriels et sources Pascal

    Le problème en ce bas monde est que les imbéciles sont sûrs d'eux et fiers comme des coqs de basse cour, alors que les gens intelligents sont emplis de doute. [Bertrand Russell]
    La tolérance atteindra un tel niveau que les personnes intelligentes seront interdites de toute réflexion afin de ne pas offenser les imbéciles. [Fiodor Mikhaïlovitch Dostoïevski]

  7. #7
    Rédacteur/Modérateur

    Avatar de Roland Chastain
    Homme Profil pro
    Enseignant
    Inscrit en
    Décembre 2011
    Messages
    4 072
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Décembre 2011
    Messages : 4 072
    Points : 15 462
    Points
    15 462
    Billets dans le blog
    9
    Par défaut
    Citation Envoyé par Alcatîz Voir le message
    Étant donné que la méthode Paint redessine la fenêtre à chaque fois qu'elle est invalidée, la fonction GetClientRect peut te retourner à tout moment la taille de la zone client ; il y a peu de modifications à faire au programme pour que tous les calculs de coordonnées se fassent relativement à cette taille.
    Merci Alcatîz pour cette suggestion. Je n'ai pas encore refait le programme, mais j'ai fait la fenêtre.

    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
    program ClientRect3;
    {&PMTYPE PM}
    uses Windows, OWindows, Couleurs;
     
    type
      pFenetre = ^tFenetre;
      tFenetre = object(tWindow)
        pinceauFond: hBrush;
        constructor Init(aParent: pWindowsObject; aTitle: pChar);
        procedure GetWindowClass(var aWndClass: tWndClass); virtual;
        procedure Paint(paintDC: hDC; var paintInfo: tPaintStruct); virtual;
        procedure WMKeyDown(var Msg : tMessage); virtual wm_First + wm_keyDown;
        destructor Done; virtual;
      end;
     
      tProgramme = object(tApplication)
        procedure InitMainWindow; virtual;
      end;
     
    constructor tFenetre.Init(aParent: pWindowsObject; aTitle: pChar);
    var
      i: longInt;
    begin
      tWindow.Init(aParent, aTitle);
      attr.style := ws_OverlappedWindow;
      pinceauFond := GetStockObject(HOLLOW_BRUSH);
    end;
     
    procedure tFenetre.GetWindowClass(var aWndClass: tWndClass);
    begin
      tWindow.GetWindowClass(aWndClass);
      aWndClass.hbrBackground := pinceauFond;
    end;
     
    procedure tFenetre.Paint(paintDC: hDC; var paintInfo: tPaintStruct);
    var
      ancienCrayon, crayon: hPen;
      ancienPinceau, pinceau: hBrush;
      r: tRect;
    begin 
      crayon := CreatePen(ps_Solid, 1, OrangeRed);
      ancienCrayon := SelectObject(paintDC, crayon);
      pinceau := GetStockObject(BLACK_BRUSH);
      ancienPinceau := SelectObject(paintDC, pinceau);
     
      GetClientRect(hWindow, r);
      Rectangle(paintDC, r.left, r.top, r.right, r.bottom);
     
      SelectObject(paintDC, ancienPinceau);
      DeleteObject(pinceau);
      SelectObject(paintDC, ancienCrayon);
      DeleteObject(crayon);
    end;
     
    procedure tFenetre.WMKeyDown (var Msg : tMessage);
    begin
      CloseWindow;
    end;
     
    destructor tFenetre.Done;
    begin
      DeleteObject(pinceauFond);
      tWindow.Done;
    end;
     
    procedure tProgramme.InitMainWindow;
    begin
      MainWindow := New(pFenetre, Init(nil, 'tWindow.Paint'));
    end;
     
    var
      prog: tProgramme;
     
    begin
      prog.Init('cercle');
      prog.RUN;
      prog.Done;
    end.
    J'ai réuni dans une archive les trois modèles de fenêtre (sources et exécutables).
    Fichiers attachés Fichiers attachés
    Mon site personnel consacré à MSEide+MSEgui : msegui.net

  8. #8
    Rédacteur/Modérateur

    Avatar de Roland Chastain
    Homme Profil pro
    Enseignant
    Inscrit en
    Décembre 2011
    Messages
    4 072
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Décembre 2011
    Messages : 4 072
    Points : 15 462
    Points
    15 462
    Billets dans le blog
    9
    Par défaut
    Voici le programme refait, avec une fenêtre redimensionnable. Le repère et la courbe sont redimensionnés en même temps que la fenêtre.

    Par contre les dimensions du repère mathématique sont constantes. On peut modifier les valeurs à condition de ne pas changer le rapport entre xMin et xMax, yMin et yMax : parce qu'en traçant le repère j'ai supposé qu'il avait pour origine le centre de l'image.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    procedure tFenetre.TraceCourbe(aDC: hDC;
                                   aFonction: tFonction;
                                   aCouleur: tColorRef;
                                   l, t, w, h, x0, y0: integer);
    const
      xMin = -7.0;
      xMax = -xMin; // ne pas changer
      yMin = -7.0;
      yMax = -yMin; // ne pas changer
      dx = 2 / 100;
    Fichiers attachés Fichiers attachés
    Mon site personnel consacré à MSEide+MSEgui : msegui.net

  9. #9
    Expert confirmé

    Inscrit en
    Août 2006
    Messages
    3 942
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 3 942
    Points : 5 654
    Points
    5 654
    Par défaut
    Peo,
    Citation Envoyé par Roland Chastain Voir le message
    Par contre les dimensions du repère mathématique sont constantes. On peut modifier les valeurs à condition de ne pas changer le rapport entre xMin et xMax, yMin et yMax : parce qu'en traçant le repère j'ai supposé qu'il avait pour origine le centre de l'image.
    Tu connais donc la prochaine étape.
    Si les cons volaient, il ferait nuit à midi.

  10. #10
    Rédacteur/Modérateur

    Avatar de Roland Chastain
    Homme Profil pro
    Enseignant
    Inscrit en
    Décembre 2011
    Messages
    4 072
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Décembre 2011
    Messages : 4 072
    Points : 15 462
    Points
    15 462
    Billets dans le blog
    9
    Par défaut
    Citation Envoyé par droggo Voir le message
    Peo,

    Tu connais donc la prochaine étape.
    Voici la nouvelle version du programme.

    Il y a toujours des constantes, mais elles sont au bon endroit maintenant et on peut les modifier librement.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    procedure tFenetre.Paint(paintDC: hDC; var paintInfo: tPaintStruct);
    const
      xMin = +0.0;
      xMax = +2.0;
      yMin = +0.0;
      yMax = +2.0;
      dx = 1 / 100;
    L'origine du repère, au lieu d'être au centre de l'écran, peut être n'importe où, même en dehors de l'écran. Sa position sur l'écran est calculée à partir de la taille actuelle de la zone client et de l'intervalle choisi.
    Fichiers attachés Fichiers attachés
    Mon site personnel consacré à MSEide+MSEgui : msegui.net

Discussions similaires

  1. Réponses: 4
    Dernier message: 18/05/2010, 11h19
  2. Réponses: 6
    Dernier message: 09/02/2009, 13h28
  3. Réponses: 6
    Dernier message: 24/11/2007, 18h48
  4. Résultat bizarre d'une fonction numérique simple
    Par feynman dans le forum Fortran
    Réponses: 9
    Dernier message: 19/11/2007, 22h07
  5. Lire une fonction numérique sur le clavier
    Par ladognon dans le forum Langage
    Réponses: 3
    Dernier message: 08/04/2006, 19h07

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