Calculer le centre de masse avec plusieurs repères

Le problème exposé dans ce sujet a été résolu.

Bonjour,

J’ai besoin de calculer le centre de masse d’objets se trouvant dans différent repère. Imaginons la situation suivante :

Soit un repère $R$ de composantes $(x, y, z)$. On a :

  • Un point $A$ de coordonnées $(0, 1, 1) \in R$ et de masse $m = 0.33$;
  • Un point $B$ de coordonnées $(2, 0, 1) \in R$ et de masse $m = 0.42$;
  • Un repère $R_1$ de composantes $(x_1, y_1, z_1)$ et aux coordonnées $(5, 2, 0) \in R$;
    • Un point $C$ de coordonnées $(0, 1, 1) \in R_1$ et de masse $m = 0.33$;
    • Un point $D$ de coordonnées $(2, 0, 1) \in R_1$ et de masse $m = 0.42$;

Comment calculer le centre de masse de ce système de point ? Je sais le faire dans un repère mais pas avec des repères imbriqués… Je précise que ce n’est pas un exercice de cours, je ne demande de toute façon pas la réponse mais juste la méthode.

Merci à vous ! :)

Le centre de masse c’est la moyenne pondérée par les masses, non ?

Le fait d’avoir un deuxième repère, ça ne t’empêche pas de réécrire les points exprimés dans ce deuxième repère dans le premier. Tu peux faire ce passage et donc reprendre ta formule habituelle

En fait je souhaiterai adapter la méthode à un arbre en C++. Pour ne pas casser la structure de l’arbre, il faut que je fasse des appels récursifs.. Voici ce que j’ai fait pour le moment, j’ai bien détaillé :

 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
QVector3D Part::computeMassCenter() const
{
    if (m_parts.size() > 0) {
        // Si la méthode n'est pas appelée sur une feuille
        QVector3D massCenter(0, 0, 0);

        for (const Part &part : getParts()) {
            if (part.getParts().size() > 0) {
                /* Si un noeud a des enfants, je calcule son centre de masse en 
                 * appelant cette même fonction que je multiplie par
                 * la masse du noeud (calculé à partir de la masse des enfants) 
                 * obtenue avec la méthode getMass().
                 */
                massCenter += part.computeMassCenter() * part.getMass();
            } else  {
                /* Sinon, c'est que c'est une feuille, du coup je retourne
                 * directement son centre de masse.
                 */
                massCenter += getPosition() * getMass();
            }
        }
        // Je retourne le résultat en divisant par la masse totale. 
        return massCenter / getMass();
    }

    /* Si la méthode est appelée sur une feuille, je retourne directement sa position,
     * c'est son centre de masse
     */
    return getPosition();
}

Le problème c’est qu’elle me retourne le vecteur $(5, 2, 0)$ pour le système présenté dans le premier message, ce qui est faux…

+0 -0
Banni

Salut,

Ligne 19, ça ne devrait pas être plutôt part.getPosition() et part.getMass() ? Et ce qu’il y a dans ton else ce n’est pas un cas particulier déjà traité dans ton if ?

edit : Sinon ce n’était pas très clair ce que tu essayais de faire dans ton premier message. Que viennent faire ces repères différents ? Au final on doit tout ramener dans le même repère pour effectuer les calculs, non ?

+0 -0

Je trouvais assez clair l’exemple des repères, c’est pour ça que je l’ai choisi. Mais on peux très bien remplacer les repères par des objets parents qui ont eux-mêmes des enfants. Chaque feuille de l’arbre possède une masse et tous les nœuds (même les feuilles) possèdent également une position. Je suis totalement débutant avec les algorithmes impliquant des arbres, j’ai du mal à les exprimer.. :-°

Ligne 19, ça ne devrait pas être plutôt part.getPosition() et part.getMass() ?

Exact.

Et ce qu’il y a dans ton else ce n’est pas un cas particulier déjà traité dans ton if ?

Comment ça ?

Merci pour vos réponses !

Au final on doit tout ramener dans le même repère pour effectuer les calculs, non ?

On peut se contenter de ramener le centre de l’ensemble des points qui sont dans le deuxième repère.

+1 -0

Si tu as effectivement oublié les deux part. ligne 19, alors ton if ligne 8 ne sert à rien (fais tourner le code à la main !). Et dans ce cas, ce que tu calcules, c’est le « centre de masse » des points en supposant que toutes leurs coordonnées sont exprimées dans un seul et même repère. Il manque une opération de translation avant de retourner ligne 23 (que tu peux faire apparaître comme indiqué par @adri1).

Du coup après pas mal de réflexion, j’ai réussi à faire ce que je voulais faire. Merci à vous ! Voici ce que ça me donne :

 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
/**
 * @brief retourne la position absolue d'un atome.
 */
QVector<Part> Part::getAbsoluteAtoms() const
{
    QVector<Part> atoms;

    for (Part part : m_parts) {
        if (part.getParts().length() == 0) {
            part.setPosition(part.getPosition() + m_position);
            atoms.append(part);
        } else {
            atoms.append(part.getAbsoluteAtoms());
        }
    }

    return atoms;
}

QVector3D Part::computeMassCenter() const
{
    if (m_parts.length() > 0) {
        QVector<Part> atoms = getAbsoluteAtoms();
        QVector3D num(0, 0, 0);

        for (const Part &atom : atoms) {
            num += atom.getMass() * atom.getPosition();
        }

        return num / getMass();
    } else {
        return m_position;
    }
}
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte