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

Lazarus Pascal Discussion :

Rotation excentrée : comment faire ? (simulation d'un GPS) [Lazarus]


Sujet :

Lazarus Pascal

  1. #1
    Nouveau membre du Club
    Homme Profil pro
    Consultant en Business Intelligence
    Inscrit en
    novembre 2015
    Messages
    21
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yonne (Bourgogne)

    Informations professionnelles :
    Activité : Consultant en Business Intelligence

    Informations forums :
    Inscription : novembre 2015
    Messages : 21
    Points : 26
    Points
    26
    Par défaut Rotation excentrée : comment faire ? (simulation d'un GPS)
    Je cherche à modifier la simulation d'un GPS aéronautique :
    Actuellement la carte se déplace (dans les plans verticaux et horizontaux) et l'avion tourne selon le cap à suivre.
    Tout fonctionne parfaitement.

    J'aimerais le faire évoluer afin que cela soit plus réaliste afin d'obtenir ceci :

    Nom : Rotation Carte1.png
Affichages : 116
Taille : 59,1 KoNom : Rotation Carte.png
Affichages : 111
Taille : 160,9 Ko

    L'avion reste vertical au centre de l'écran, la carte se déplace et tourne selon le cap à suivre.

    Le problème que je n'arrive pas à résoudre est le suivant : sauf erreur de ma part, le centre de rotation est excentré, il se trouve à l'emplacement de l'avion.
    Comment faire cette rotation ?
    J'ai regardé les documents de Gilles Vasseur (merci à lui) et m'en suis inspiré. Suis-je passé à côté d'une explication ?
    J'ai joint le code source qui permet de simuler les déplacements de l'avion selon un plan de vol.
    Il reste à programmer le dernier trackbar (Angle de la partie MAP).
    Peut-être cela se résume-t-il à une ligne ou quelques lignes de code qui m' échappent.
    Si tel est le cas je suis preneur sinon tant pis je ferai avec l'existant. (Si vous avez besoin d'informations supplémentaires, n'hésitez pas à demander)

    Le programme d'essai :

    Nom : simulateur.PNG
Affichages : 100
Taille : 289,2 Ko
    Fichiers attachés Fichiers attachés

  2. #2
    Modérateur
    Avatar de tourlourou
    Homme Profil pro
    Biologiste ; Progr(amateur)
    Inscrit en
    mars 2005
    Messages
    3 688
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 59
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Biologiste ; Progr(amateur)

    Informations forums :
    Inscription : mars 2005
    Messages : 3 688
    Points : 10 632
    Points
    10 632
    Billets dans le blog
    6
    Par défaut
    Bonsoir,
    La fonction TBGRABitmap.FilterRotate doit répondre à ton besoin.
    Delphi 5 Pro - Delphi 10.4 Rio Community Edition - CodeTyphon 6.90 sous Windows 10 ; CT 6.40 sous Ubuntu 18.04 (VM)
    . Ignorer la FAQ Delphi et les Cours et Tutoriels Delphi nuit gravement à notre code !

  3. #3
    Nouveau membre du Club
    Homme Profil pro
    Consultant en Business Intelligence
    Inscrit en
    novembre 2015
    Messages
    21
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yonne (Bourgogne)

    Informations professionnelles :
    Activité : Consultant en Business Intelligence

    Informations forums :
    Inscription : novembre 2015
    Messages : 21
    Points : 26
    Points
    26
    Par défaut
    Citation Envoyé par tourlourou Voir le message
    Bonsoir,
    La fonction TBGRABitmap.FilterRotate doit répondre à ton besoin.
    Effectivement après quelques essais cela semblerait être le cas, du moins c'est la piste à suivre.
    Ne maitrisant pas encore bien cette fonction, je n'obtiens pas exactement ce que je veux, il faut que j'affine les calculs.

    Cela va me prendre un peu de temps (peu de disponibilités en ce moment).
    Quand j'aurai terminé, je reviendrai poster pour indiquer que c'est résolu et posterai les nouvelles sources afin qu'elles servent d'exemple.

    Merci.

  4. #4
    Membre chevronné

    Homme Profil pro
    Directeur de projet
    Inscrit en
    mai 2013
    Messages
    764
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Directeur de projet
    Secteur : Service public

    Informations forums :
    Inscription : mai 2013
    Messages : 764
    Points : 2 241
    Points
    2 241
    Par défaut Ca tourne carré
    Bonjour,

    Une rotation autour d'un point (xc, yc) est toujours de la forme :
    xr = xc + (x-xc)*cos(a) - (y-yc)*sin(a)
    yr = yc + (x-xc)*sin(a) + (y-yc)*cos(a)

    Mais, pour éviter des trous, on cherche en général l'inverse, c'est à dire trouver pour chaque point de destination (xr, yr) quel est le point (x, y) d'origine.

    Cela peut se faire en ne calculant qu'une fois les points correspondants aux 4 angles et en appliquant une transformation entière (double Bresenham) aux deux triangles qui composent le rectangle. C'est rapide. Mais le plus simple reste bien sûr d'utiliser une bibliothèque.

    Il faut prévoir une image source plus grande que l'image cible qui contienne au moins les 4 points correspondants aux angles de l'image cible.

    Salutations
    Ever tried. Ever failed. No matter. Try Again. Fail again. Fail better. (Samuel Beckett)

  5. #5
    Expert confirmé
    Avatar de BeanzMaster
    Homme Profil pro
    Amateur Passionné
    Inscrit en
    septembre 2015
    Messages
    1 876
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Amateur Passionné
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : septembre 2015
    Messages : 1 876
    Points : 4 258
    Points
    4 258
    Billets dans le blog
    2
    Par défaut
    Salut tu peux jeter un oeil a cette discussion aussi https://www.developpez.net/forums/d1.../#post11003920
    • "L'Homme devrait mettre autant d'ardeur à simplifier sa vie qu'il met à la compliquer" - Henri Bergson
    • "Bien des livres auraient été plus clairs s'ils n'avaient pas voulu être si clairs" - Emmanuel Kant
    • "La simplicité est la sophistication suprême" - Léonard De Vinci
    • "Ce qui est facile à comprendre ou à faire pour toi, ne l'est pas forcément pour l'autre." - Mon pèrei

    Mes projets sur Github - Blog - Site DVP

  6. #6
    Rédacteur/Modérateur

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

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : décembre 2011
    Messages : 3 910
    Points : 13 979
    Points
    13 979
    Billets dans le blog
    8
    Par défaut
    Bonjour !

    Voici la solution que je proposerais.

    Attention ! Je n'ai pas inclus l'image korea.jpg. Il faut la copier à partir de la pièce jointe du premier message.

    À la place des trackbars, j'ai utilisé un timer. La vitesse de l'avion est constante. On modifie le cap de l'avion au moyen des flèches gauche et droite du clavier.

    L'avion est dessiné toujours au même endroit. Sa position est recalculée à la fin de chaque intervalle de temps. En fonction de sa position et de son cap, on redessine la carte.

    En espérant que cet exemple fasse avancer la discussion.

    P.-S. En jouant avec la version originale de l'exemple, j'avais fait une première correction pour que l'avion tourne sur son centre (qui ne correspond pas au centre de l'image), et j'avais agrandi le composant pour que l'ombre ne soit pas coupée. Dans cette nouvelle version, ça ne se justifie plus d'agrandir le composant, mais je n'ai pas pensé à annuler cette modification.

    Au fait, normalement, l'ombre devrait tourner aussi. Donc il faudrait l'avoir sur une image séparée.
    Fichiers attachés Fichiers attachés

  7. #7
    Nouveau membre du Club
    Homme Profil pro
    Consultant en Business Intelligence
    Inscrit en
    novembre 2015
    Messages
    21
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yonne (Bourgogne)

    Informations professionnelles :
    Activité : Consultant en Business Intelligence

    Informations forums :
    Inscription : novembre 2015
    Messages : 21
    Points : 26
    Points
    26
    Par défaut
    Merci pour vos retours et pour le temps que vous m'avez consacré.

    @Roland Chastain,
    La solution proposée est intéressante, je la garde en mémoire pour d'autres applications car, à première vue, elle ne me parait pas adaptée à la situation.

    En effet, la vitesse n'est pas constante, elle varie énormément en fonction des phases de pilotage (décollage, atterrissage, engagement, évasive ..).
    Je ne dispose que des coordonnées de la position de l'aéronef. Connaitre la vitesse va donc me demander des calculs supplémentaires. Je préfère m'en abstenir.
    Merci pour ce retour.

    Je vais utiliser la fonction TBGRABitmap.FilterRotate que m'avait suggéré tourlourou. Elle fait le job.
    Il me reste à tester la fluidité dans le simulateur et peut-être serai-je amené à prendre la solution préconisée par Roland Chastain.
    Ci-joint le source avec la modification. Version Lazarus2.7z

  8. #8
    Rédacteur/Modérateur

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

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : décembre 2011
    Messages : 3 910
    Points : 13 979
    Points
    13 979
    Billets dans le blog
    8
    Par défaut
    Ah, je vois que je n'avais pas bien saisi la "problématique". Je comprends mieux maintenant le pourquoi des trackbars.

    Dans ce cas, voici ma solution. J'espère ne pas être encore à côté de la plaque.

    Il faut toujours récupérer l'image korea.jpg du projet original.

    Le code que vous avez attaché à votre dernier message, je n'ai pas pu l'essayer directement parce que je n'ai pas Code Typhon.

    Pour la fluidité, je crois qu'il faudrait travailler sur une copie partielle de la carte, et faire tourner seulement ce rectangle-là. Mais bon, je vois que vous avez déjà marqué "résolu", donc je n'insisterai pas.
    Fichiers attachés Fichiers attachés

  9. #9
    Membre chevronné

    Homme Profil pro
    Directeur de projet
    Inscrit en
    mai 2013
    Messages
    764
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Directeur de projet
    Secteur : Service public

    Informations forums :
    Inscription : mai 2013
    Messages : 764
    Points : 2 241
    Points
    2 241
    Par défaut

    Bonjour,

    Pourquoi pour les angles les trackbars se baladent de -360 à +360 (deux tours) ? -179..+180 ou 0..179 suffisent. En utilisant la roulette des souris avec un code comme celui-ci on évite de nombreux affichages intermédiaires qui sont finalement assez longs :
    Code PASCAL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    procedure TForm1.TbMouseWheel(Sender: TObject; Shift: TShiftState;  WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
    var delta : Int32;
    begin
       delta := WheelDelta div 64 + TTrackBar(Sender).Position;    // Ma souris fait des pas "unitaires" de 120 : diviser par 64 ne coûte qu'un décalage
       while delta  < TTrackBar(Sender).Min do delta += TTrackBar(Sender).Max - TTrackBar(Sender).Min + 1;    // En général plus efficace qu'une division/modulo
       while delta  > TTrackBar(Sender).Max do delta -= TTrackBar(Sender).Max - TTrackBar(Sender).Min + 1;
       TTrackBar(Sender).Position := delta;
    end;
    Quelques remarques :
    • L'avion ne tourne pas sur son propre centre mais sur le point inférieur droit.
    • L'angle de la carte n'est pas affiché.
    • Pourquoi actualiser la position X dans un mouvement Y et réciproquement la position Y dans un mouvement X ?
    • Une carte en png serait exempte des mosquitos (points parasites autour des contours) du jpeg.
    • La lenteur de la rotation est peut être due à la bibliothèque (calculs en flottants)


    Salutations
    Ever tried. Ever failed. No matter. Try Again. Fail again. Fail better. (Samuel Beckett)

  10. #10
    Nouveau membre du Club
    Homme Profil pro
    Consultant en Business Intelligence
    Inscrit en
    novembre 2015
    Messages
    21
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yonne (Bourgogne)

    Informations professionnelles :
    Activité : Consultant en Business Intelligence

    Informations forums :
    Inscription : novembre 2015
    Messages : 21
    Points : 26
    Points
    26
    Par défaut
    @ Guesset,
    Pour répondre globalement à toutes vos questions c'est tout simplement parce que ce programme est avant tout un prototype pour test de faisabilité.
    Je ne tiens pas compte d'une quelconque optimisation, cela viendra dans un second temps.
    Le cap variant de 0 à 360°, ce sera la plage d'utilisation dans le logiciel qui est finalisé mais dans lequel l'aéronef tourne et le carte se déplace.
    Pour davantage coller à la réalité, l'aéronef doit rester immobile au centre de l'écran, la carte se déplace et s'oriente en fonction du plan de vol.
    Ce qui me posait problème c'était la rotation excentrée. Le reste est bien géré dans le logiciel final.
    La carte est au format jpg parce que le poids des pièces jointes est limité à 2 Mo, celle que j'utilise au format png ne me permettait pas de poster la totalité des fichiers nécessaires au programme.
    Le logiciel simule un "Center Pedestal Display" ou CPD embarqué dans les avions de chasse.
    Merci pour vos remarques qui révèlent un souci de perfection : j'apprécie.

    @Roland Chastain,
    Je vais regarder votre nouvelle mouture et vous tiens au courant. Certainement ce week-end. Merci.
    La problèmatique étant très spécifique et ne m'étant pas étendu dessus, je comprends qu'elle vous échappe un peu.
    Je vais changer le fichier joint de mon dernier post (certainement ce week-end aussi): je pensais avoir mis la version pour lazarus(c'est raté).

    Maintenant il ne me reste plus qu'à ouvrir un nouveau post : j'ai un problème de fuite mémoire avec le composant BGRAGraphiccontrol (du moins je pense que le souci vient de ce composant) que je n'arrive pas résoudre.

  11. #11
    Rédacteur/Modérateur

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

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : décembre 2011
    Messages : 3 910
    Points : 13 979
    Points
    13 979
    Billets dans le blog
    8
    Par défaut
    Citation Envoyé par AlainFt Voir le message
    Maintenant il ne me reste plus qu'à ouvrir un nouveau post : j'ai un problème de fuite mémoire avec le composant BGRAGraphiccontrol (du moins je pense que le souci vient de ce composant) que je n'arrive pas résoudre.
    Oui, j'ai vu qu'il y a des choses qui ne sont pas correctes de ce point de vue. Des objets créés (voire créés plusieurs fois) et non détruits. C'est facile à corriger mais j'attends de voir la dernière version de votre code pour vous indiquer les erreurs si vous ne les avez pas trouvées d'ici là. En tout cas ce n'est pas un problème dans le composant.

  12. #12
    Nouveau membre du Club
    Homme Profil pro
    Consultant en Business Intelligence
    Inscrit en
    novembre 2015
    Messages
    21
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yonne (Bourgogne)

    Informations professionnelles :
    Activité : Consultant en Business Intelligence

    Informations forums :
    Inscription : novembre 2015
    Messages : 21
    Points : 26
    Points
    26
    Par défaut
    @ Roland Chastain
    Finalement levé tôt, j'ai un peu de temps pour répondre plus tôt que prévu.
    Votre code est beaucoup plus simple et optimisé que le mien, je suis preneur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    procedure TForm1.GCMapRedraw(Sender: TObject; Bitmap: TBGRABitmap);
    begin
      //========================================================
      // Affichage du déplacement horizontal ou vertical
      // L'angle de rotation est mis à zéro
      //========================================================
      Bitmap.PutImageAngle(200, 200, bmp, TbRafale.Position, rfHalfCosine, Xpos, Ypos);
    end;
    Voici le mien :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    procedure TForm1.GCMapRedraw(Sender: TObject; Bitmap: TBGRABitmap);
    begin
      //========================================================
      // Affichage du déplacement horizontal ou vertical
      // L'angle de rotation est mis à zéro
      //========================================================
      Origine:=Tpointf.Create(Xpos+220,Ypos+308); //(2048,2048)
       Bitmap.PutImageAngle(-Xpos, -Ypos, bmpMap.FilterRotate(Origine,tbMap.Position,false), 0, rfHalfCosine, 0, 0);
    end;
    Ce que je ne comprends pas dans votre code ce sont les coordonnées 200,200. Que représentent-elles ? Comment sont elles obtenues ou calculées ?
    Cela semble être les coordonnées du centre du composant GCmap dont les dimensions sont 400x400. Est-ce bien cela ?
    Quand je redimensionne ce composant aux dimensions d'utilisation 452 x 601 la rotation n'est plus correcte.

    Ci-joint ma version Lazarus.
    Fichiers attachés Fichiers attachés

  13. #13
    Rédacteur/Modérateur

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

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : décembre 2011
    Messages : 3 910
    Points : 13 979
    Points
    13 979
    Billets dans le blog
    8
    Par défaut
    Citation Envoyé par AlainFt Voir le message
    Ce que je ne comprends pas dans votre code ce sont les coordonnées 200,200. Que représentent-elles ? Comment sont elles obtenues ou calculées ?
    Cela semble être les coordonnées du centre du composant GCmap dont les dimensions sont 400x400. Est-ce bien cela ?
    Oui, ce sont bien les coordonnées du centre du composant GCMap, et ce sont aussi (et surtout) les coordonnées du centre de l'avion. Par facilité, j'avais positionné le composant GCRafale de telle sorte que le centre de l'avion coïncide avec le centre du composant GCMap.

    Donc à vous de remplacer ces coordonnées en fonction de l'endroit où vous décidez de placer l'avion.

    Au sujet de ce code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Bitmap.PutImageAngle(-Xpos, -Ypos, bmpMap.FilterRotate(Origine,tbMap.Position,false), 0, rfHalfCosine, 0, 0);
    Effectivement, il est inutilement compliqué, puisque vous avez deux rotations, dont une avec un angle 0. Autant utiliser un simple PutImage, dans ce cas-là, au lieu de PutImageAngle.

    Mais en outre ce code entraîne une fuite de mémoire, puisqu'à chaque appel la fonction FilterRotate crée un nouveau bitmap qui ne sera jamais libéré.

    Autre point à prendre en compte : ça ne sert à rien de faire tourner toute la carte à chaque fois (comme le fait, sauf erreur de ma part, le code ci-dessus). Il vaut mieux copier le carré dont on a besoin, et ne faire tourner que ce carré. La différence de performance sera sensible, surtout si la carte est grande.

    Voici un exemple (toujours avec les mêmes coordonnées magiques "200, 200").

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    procedure TForm1.GCMapRedraw(Sender: TObject; Bitmap: TBGRABitmap);
    const
      CRacine = 1.415;
    var
      partie: TBGRABitmap;
      w: integer;
    begin
      w := Ceil(CRacine * Max(Bitmap.Width, Bitmap.Height));
      w := w div 2;
      partie := bmp.GetPart(Rect(Xpos - w, Ypos - w, Xpos + w, YPos + w)) as TBGRABitmap;
      Bitmap.PutImageAngle(200, 200, partie, TbRafale.Position, rfHalfCosine, w, w);
      partie.Free;
    end;
    Je me sers de la variable w pour déterminer la dimension du carré que je vais copier. L'idée étant que le carré soit assez grand pour toujours bien remplir le composant GCMap.

  14. #14
    Nouveau membre du Club
    Homme Profil pro
    Consultant en Business Intelligence
    Inscrit en
    novembre 2015
    Messages
    21
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yonne (Bourgogne)

    Informations professionnelles :
    Activité : Consultant en Business Intelligence

    Informations forums :
    Inscription : novembre 2015
    Messages : 21
    Points : 26
    Points
    26
    Par défaut
    Merci Roland, cela fonctionne à merveille : plus de perte de mémoire, la fluidité est excellente. Super !!!

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

Discussions similaires

  1. Internet Explorer sur PDA avec GPS : comment faire un lien vers le GPS
    Par sjachym dans le forum Général Conception Web
    Réponses: 0
    Dernier message: 21/06/2008, 00h45
  2. [Rotations] Un objet sur une planete, comment faire ?
    Par supergrey dans le forum Développement 2D, 3D et Jeux
    Réponses: 6
    Dernier message: 09/03/2008, 11h21
  3. Les rotations, je ne saisi pas comment faire
    Par tyrant dans le forum Développement 2D, 3D et Jeux
    Réponses: 2
    Dernier message: 12/11/2006, 20h39
  4. Réponses: 22
    Dernier message: 31/05/2006, 20h11
  5. Comment faire une rotation de metafile (l'angle de 90° me suffit) ?
    Par Tardiff Jean-François dans le forum Langage
    Réponses: 4
    Dernier message: 28/01/2005, 08h58

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