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

C++Builder Discussion :

Rotation d'une cible autour du centre de l'écran [Non suivi]


Sujet :

C++Builder

  1. #1
    Membre confirmé Avatar de kurul1
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    933
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 933
    Points : 466
    Points
    466
    Par défaut Rotation d'une cible autour du centre de l'écran
    Bonjour à tous

    pour vous expliquer mon problème, j'ai simplifier mon programme.

    Je désire afficher un point qui effectue une rotation autour du centre de l'écran.

    Mon problème est que cette rotation ne se passe pas correctement, le point converge vers le centre de l'écran.

    Voici mon programme

    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
     
    //---------------------------------------------------------------------------
    __fastcall TForm1::TForm1(TComponent* Owner)
            : TForm(Owner)
    {
            // Calcul les coordonnées du centre de l'écran
            XCentre = (Screen->Width / 2);
            YCentre = (Screen->Height / 2);
     
            // On fixe les coordonnées du point au départ de la cible
            X = XCentre + 100;
            Y = YCentre;
    }
    //---------------------------------------------------------------------------
    // Méthode déclancher lorsque l'on presse une touche
    void __fastcall TForm1::OnKeyPress(TObject *Sender, char &Key)
    {
            // SI l'on presse la touche esc
            if(Key == VK_ESCAPE)
            {
                    // On quitte l'application
                    Application->Terminate();
            }
     
    }
    //---------------------------------------------------------------------------
     
    void __fastcall TForm1::OnPaint(TObject *Sender)
    {
            // On fixe les couleurs pour l'arrière-plan
            Form1->Canvas->Brush->Color = clWhite;
            Form1->Canvas->Pen->Color = clWhite;
     
            // On dessine l'arrière-plan
            Form1->Canvas->Rectangle(0, 0, ClientWidth, ClientHeight);
     
            // On fixe les couleurs pour la cible
            Form1->Canvas->Brush->Color = clRed;
            Form1->Canvas->Pen->Color = clRed;
     
            // On dessine la cible
            Form1->Canvas->Ellipse((X - 20), (Y - 20), (X + 20), (Y + 20));
     
    }
    //---------------------------------------------------------------------------
     
    // Méthode de translation
    void TForm1::Translation(int Xt, int Yt)
    {
            // On calcule le nouveau X
            X += Xt;
     
            // On calule le nouveau Y
            Y += Yt;
    }
     
    // Méthode de rotation
    void TForm1::Rotation(double AngleDeg)
    {
            // Coordonnées du point après la rotation
            double xr, yr;
     
            // Angle de rotation en radiant
            double AngleRad;
     
            // On convertit l'angle exprimé en degré en radiant
            AngleRad = AngleDeg * (M_PI / 180);
     
            // On ramène le point à l'origine
            Translation(-XCentre, -YCentre);
     
            // On calcule les coordonnées du point après la rotation
            xr = (X * cos(AngleRad)) + (Y * sin(AngleRad));
            yr = (X * (sin(AngleRad) * -1)) + (Y * cos(AngleRad));
     
            // On affecte le nouveau point
            X = xr;
            Y = yr;
     
            // On ramène le point au centre de l'écran
            Translation(XCentre, YCentre);
    }
     
    // Méthode déclancher lorsque le timer arrive à expiration
    void __fastcall TForm1::OnTimer(TObject *Sender)
    {
            // On effectue la rotation
            Rotation(1);
     
            // On réaffiche l'écran
            OnPaint(Form1);
    }
    //---------------------------------------------------------------------------
    X, Y, XCentre, YCentre sont des entiers, variable de ma Form.

    Est-ce quelqu'un vois d'où peut venir le problème

    Merci d'avance[/code]

  2. #2
    Membre chevronné

    Profil pro
    Inscrit en
    Juin 2002
    Messages
    1 390
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 1 390
    Points : 1 777
    Points
    1 777
    Par défaut
    Salut !

    Il y a probablement plus simple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    double radius = 100.0; //rayon du cercle
    double step = 10.0; //pas de la rotation
    double phi = 0.0; //angle de rotation au moment du dessin
    int posx; //position X du point
    int posy; //position Y du point
    int ox; //centre de l'écran en X
    int oy; /:centre de l'écran en Y
    bool clockwise = true; //sens de rotation du point
    Depuis une form, ici pour le test, on initialise comme suit :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    ox = Width /2;
    oy = Height /2;
    //la position initiale du point est à "3 heures"
    posx = radius;
    posy = 0;
    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
    void __fastcall TForm1::Timer1Timer(TObject *Sender)
    {
    if(clockwise)
        {
        phi = phi - step;
        if(phi < 0)
            {
            phi = phi + 360;
            }
        }
    else
        {
        phi = phi + step;
        if(phi > 360)
            {
            phi = phi - 360;
            }
        }
    DrawPixel();
    }
    Chez moi, un pixel n'est pas très visible alors j'en dessine 4
    L'idée, ici est d'effacer les quatre points sur l'ancienne position
    puis de les redessiner sur la nouvelle position :

    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
    void __fastcall TForm1::DrawPixel()
    {
    //effacer les points sur l'ancienne position, ici simplement...
    Canvas->Pixels[posx - 1][posy] = Color; // == Form1->Color
    Canvas->Pixels[posx + 1][posy] = Color;
    Canvas->Pixels[posx][posy - 1] = Color;
    Canvas->Pixels[posx][posy + 1] = Color;
    //calculer la nouvelle position
    double rad = 3.14159265358979 * phi / 180.0;
    posy = oy - (sin(rad) * radius);
    posx = ox + (cos(rad) * radius);
    //dessiner les points sur la nouvelle position
    Canvas->Pixels[posx - 1][posy] = clBlack;
    Canvas->Pixels[posx + 1][posy] = clBlack;
    Canvas->Pixels[posx][posy - 1] = clBlack;
    Canvas->Pixels[posx][posy + 1] = clBlack;
    }
    Pour la vitesse on peut jouer simultanéement sur step et sur
    l'intervalle du Timer.

    A plus !

  3. #3
    Membre confirmé Avatar de kurul1
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    933
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 933
    Points : 466
    Points
    466
    Par défaut
    9a marche mais la rotation n'est pas parfaite. La cible par moment se rapproche du centre et à d'autre s'éloigne.

    Quelqu'un sait de quoi cela peut venir

    De plus, cela fonctionne quand j'ai une seule sible, mais lorsque j'en est plusieurs, les cibles tournent bien mais ne reste pas a leur place, elles sont toutes sur la même ligne.

    Pourtant, pour chaque cibles, je mémorise le rayon et l'angle de rotation

  4. #4
    Membre chevronné

    Profil pro
    Inscrit en
    Juin 2002
    Messages
    1 390
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 1 390
    Points : 1 777
    Points
    1 777
    Par défaut
    Salut !

    Je ne m'explique pas de variations plus grandes que le pixel !

    Voici le source du test. On trace un cercle sur lequel évolue un point.
    Ce point sert de référentiel à un autre cercle sur lequel évolue un
    deuxième point.

    J'utilise la class suivante :

    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
    class TRP
    {
    public :
    int radius;
    double phi;
    double step;
    int posx;
    int posy;
    TColor color;
    int *ox;
    int *oy;
        __fastcall TRP(int R, double P, double S, int *X, int *Y, TColor C);
        __fastcall ~TRP();
        void __fastcall Step();
        void __fastcall Draw(TCanvas *C);
    };
    Les méthodes de la class TRP :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    __fastcall TRP::TRP(int R, double P, double S, int *X, int *Y, TColor C)
    {
    radius = R;
    phi = P;
    step = S;
    color = C;
    //l'objet est dynamiquement lié à son référentiel à l'aide de deux pointeurs
    //ce qui simplifie le calcul. Cela va imposer, plus loin, un ordre de création précis
    ox = X;
    oy = Y;
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    __fastcall TRP::~TRP()
    {
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    void __fastcall TRP::Step()
    {
    phi = phi + step;
    if(phi > 360) {phi = phi - 360;}
    if(phi < 0){phi = phi + 360;}
    double angle = phi * 3.14159265358979 / 180;
    posx = *ox + (cos(angle) * radius);
    posy = *oy - (sin(angle) * radius);
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    void __fastcall TRP::Draw(TCanvas *C)
    {
    C->Pen->Color = color;
    //Dessiner le cercle sur lequel se déplace la cible
    C->Ellipse(*ox - radius, *oy - radius, *ox + radius , *oy + radius);
    //Dessiner le cercle entourant la cible
    C->Ellipse(posx - 10, posy - 10, posx + 10, posy + 10);
    }
    Usage avec une Form (TForm1)

    Variables globales
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Graphics::TBitmap *Bitmap = new Graphics::TBitmap;
    TList *Points = new TList;
    int Ox;
    int Oy;
    Construction des points dans le constructeur de la form

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    __fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
    {
    Color = clWhite;
    Ox = ClientWidth / 2;
    Oy = ClientHeight / 2;
    //Le centre de l'écran est le référentiel du permier cercle
    TRP *P1 = new TRP(100, 0, 10, &Ox, &Oy, clRed);
    Points->Add(P1);
    //Le point en rotation sur le premier cercle devient le référentiel du deuxième cercle
    TRP *P2 = new TRP(50, 90, -5, &P1->posx, &P1->posy, clBlue);
    Points->Add(P2);
    }
    La méthode OnTimer du Timer

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    void __fastcall TForm1::Timer1Timer(TObject *Sender)
    {
    for(int j = 0; j < Points->Count; j++)
        {
        TRP *P = (TRP*)Points->Items[j];
        P->Step();
        }
    DrawBitmap();
    }
    La méthode qui dessine le bitmap à l'écran

    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
    void __fastcall TForm1::DrawBitmap() //déclarée en public dans la class de TForm1
    {
    if(Bitmap != NULL)
        {
        int w = ClientWidth;
        int h = ClientHeight;
        if(Bitmap->Width != w){Bitmap->Width = w;}
        if(Bitmap->Height != h){Bitmap->Height = h;}
        TCanvas *C = Bitmap->Canvas;
        C->Pen->Color = Color; C->Pen->Mode = pmCopy; C->Pen->Style = psSolid;
        C->Brush->Color = Color; C->Brush->Style = bsSolid;
        C->Rectangle(0,0,w,h);
        C->Brush->Style = bsClear;
        for(int j = 0; j < Points->Count; j++)
            {
            TRP *P = (TRP*)Points->Items[j];
            P->Draw(C);
            }
        Canvas->Draw(0, 0, Bitmap);
        }
    }

    Une méthode OnResize pour recentrer

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    void __fastcall TForm1::FormResize(TObject *Sender)
    {
    Ox = ClientWidth / 2;
    Oy = ClientHeight / 2;
    }
    Dans la Onclose il faut libérer la mémoire

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
    {
    delete Bitmap; 
    Bitmap = NULL; //au cas où...
    for(int j = 0; j < Points->Count; j++)
        {
        TRP* P =(TRP*)Points->Items[j];
        delete P;
        }
    Points->Clear();
    delete Points;
    Action = caFree;
    }
    A plus !

  5. #5
    Membre confirmé Avatar de kurul1
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    933
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 933
    Points : 466
    Points
    466
    Par défaut
    En fait moi, mes cibles tournent toutes dans le même sens suivant la même rotation. Elle sont positionné de façon aléatoire.

    Or pour l'instant, j'arrive à toutes les faires tourner mais elle ne reste pas à leur place, elle se trouvent toutes sur la même ligne.

  6. #6
    Membre confirmé Avatar de kurul1
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    933
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 933
    Points : 466
    Points
    466
    Par défaut
    Personne n'a de solution à mon problème.

    Je vais essayer d'être plus clair

    J’affiche à l'écran un certain nombre de cibles positionnées aléatoirement.
    Je voudrais effectuer une rotation de toutes ces cibles autour du centre de l'écran.

    Pour chaque cible, je connais les coordonnées de son centre (X, Y)

  7. #7
    Membre chevronné

    Profil pro
    Inscrit en
    Juin 2002
    Messages
    1 390
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 1 390
    Points : 1 777
    Points
    1 777
    Par défaut
    Salut !

    Probablement qu'il te faut calculer l'angle de départ à l'aide de la position du point.
    Dans ce que j'ai donné, il suffit de rajouter un constructeur pour la class TRP qui
    va se différencier du premier par un paramètre TPoint pour ce qui concerne la position
    initiale du point :

    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
    __fastcall TRP::TRP(double S, TPoint P, int *Ox, int *Oy, TColor C)
    {
    step = S;
    //Les pointeurs rendent l'utilisation plus intéressante... mais... ... ...
    ox = Ox;
    oy = Oy;
    //On raisonne sur un cercle trigonométrique
    posx = P.x - *ox;
    posy = *Oy - P.y;
    radius = hypot(posx, posy);
    //Calcul de l'angle de départ
    phi = 180.0 / 3.14159265358979 * acos(posx / radius);
    if(posy < 0)
        {
        phi = 360 - phi;
        }
    }
    A plus !

  8. #8
    Membre éclairé
    Inscrit en
    Juin 2005
    Messages
    644
    Détails du profil
    Informations professionnelles :
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2005
    Messages : 644
    Points : 754
    Points
    754
    Par défaut
    il est possible d'utiliser les possibilitées offertes par la librairie
    graphics32 que l'on peut trouver
    http://graphics32.org/wiki/
    si non la possiblité deja proposé de calculer lle rayon ( distance au centre d'ecran à t=0, l'angle initial puis de modifier cet angle avec timer, hologe systeme, bouton est le seul moyen. Suivant PC taille de l'image et vitesse de rotaion, il peut necessiter une grosse charge au CPU car le nombre de pixels à eteindre et à alumer ailleur devient grand. GR32 gere cela tres bien. ils annonce des acces jusqu'a 100 X plus rapide que des actions du type canvas.pixel[,]=
    J'ai verifié qu'il etait tres possible de faire tourner des images de taille 500X500 pixels à 1 Hz de facon tres 'smooth'

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. comment faire une cible qui se déplace sur un écran
    Par Mordenkainen dans le forum LabVIEW
    Réponses: 0
    Dernier message: 15/04/2011, 11h01
  2. Réponses: 7
    Dernier message: 03/06/2010, 21h57
  3. [OpenGL] centre de rotation d'une arcball
    Par lucmoulinier dans le forum OpenGL
    Réponses: 0
    Dernier message: 23/02/2009, 16h30
  4. Réponses: 2
    Dernier message: 25/03/2007, 21h49
  5. Rotation d'un rectangle autour du centre de gravité
    Par bucheron dans le forum Algorithmes et structures de données
    Réponses: 13
    Dernier message: 22/06/2004, 11h01

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