Trouver le barycentre à partir des coordonnées de 4 points

Bonjour,

Savez-vous comment trouver le barycentre d'une forme définit par 4 point sur python ?

Merci pour votre aide !


Windows / Chrome 108.0.0.0

7 réponses

Résumé de la discussion

Le calcul du barycentre d'une forme définie par quatre points en Python soulève la distinction entre centre de gravité et barycentre (ou isobarycentre) selon les poids attribués. Des réponses utilisent les formules classiques: avec poids égaux, OG est la moyenne des coordonnées OA, OB, OC et OD; en Python, og = (sum x / n, sum y / n). Pour des formes convexes comme un trapèze, le centre peut être celui du polygone ou calculé par intégration sur la surface pour obtenir le centre de poussée. En cas de variations de hauteur, la position de poussée diffère du barycentre et peut nécessiter un maillage ou une somme pondérée locale.

Bobot (l’IA à votre service)
  1. Bonjour, le centre est le croisement des médianes

    J'ai bon ?

    1
    1. Bonjour,

      géométriquement oui, cela dit, vu qu'il dit avoir les coordonnées des points, y'a plus simple.

      Mais on y reviendra quand il aura daigné respecter les règles du forum et montré qu'il a un peu cherché / réfléchi par lui-même.

      0
    2. Contributeur
      @Utilisateur anonyme

      C'est moins simple que certains le pensent.  Il ne s'agit pas du barycentre des 4 points, mais du barycentre du polygone délimité par les 4 points.

      0
    3. @yg_be

      reste à savoir si les 4 points sont dans le plan ou pas ..

      0
  2. Les 4 points ne peuvent êtres que ceux de la coupe verticale (qui pour un barrage poids, est un trapèze).
    Le barycentre restant constant sur la longueur du mur.

    1
    1. Contributeur

      Les 4 points seraient alors ceux-ci:

      xb0, xb0, xb0+Ltop, xb0+Ltop+L
      yb0, yb0+H, yb0+H,yb0
      0
    2. Contributeur
      @yg_be

      et ton barycentre:

      bcx= xb0 + (Ltop ** 2 + L * (Ltop+ L/3) ) / (L + 2 * Ltop)
      
      bcy = yb0 + H * ( Ltop + L / 3 ) / (L + 2 * Ltop)
      1
    3. @yg_be

      merci beaucoup !

      0
    4. Contributeur
      @yg_be

      plus propre:

      cr=[xb0+Ltop/2,yb0+H/2]
      ct=[xb0+Ltop+L/3,yb0+H/3]
      cb = [(cr[i]*2*Ltop+ct[i]*L)/ (L + 2 * Ltop) for i in range(len(cr))  ]
      0
  3. Modérateur

    Bonjour,

    Pour commencer le barycentre est une généralisation du centre de gravité : on considère un ensemble de vecteur (par exemple définis par les coordonnées des 4 points) et on affecte à chaque vecteur un poids (toujours 1 pour le centre de gravité, un réel arbitraire dans la généralisation du barycentre).

    Nommons A, B, C, D les quatre points (ce qui suit reste vrai quelque soit le nombre de points) ; a, b, c, d les points associé à chacun de ces points ; et G le barycentre de ce système.

    Alors pour tout point M arbitraire :

    • (a + b + c +d) MG = a.MA + b.MB + c.MC + d.MD

    En particulier, pour M = O

    • (a + b + c +d) OG = a.OA + b.OB + c.OC + d.OD
    • OG = (a / (a + b + c + d)) .OA + (b / (a + b + c + d)) .OB + (c / (a + b + c + d)) .OC + (d / (a + b + c + d)) .OD

    En particulier, si a = b = c = d (isobarycentre, où centre de gravité) :

    • OG = (1 / 4) .OA + (1 / 4) .OB + (1 / 4) .OC + (1 / 4) .OD

    En python si tes coordonnées sont stockées dans des couples oa, ob, oc, od il suffit donc de calculer :

    points = [
      (0, 10),   # OA
      (10, 10),  # OB
      (2, 0),    # OC
      (8, 0)     # OD
    ]
    og = (
        sum(x for (x, y) in points) / len(points),
        sum(y for (x, y) in points) / len(points)
    )
    print(og) # (5.0, 5.0)

    Maintenant revenons à la physique.

    • Ici la forme du barrage est convexe puisque c'est un trapèze donc pourquoi pas, mais sinon, calculer le centre de gravité à partir des angles du polygones qui défini ta forme est généralement faux.
    • Il faut bien comprendre qu'ici ce calcul d'isobarycentre revient d'un point de vue à rassembler quatre forces d'intensité a, b, c, d en une seule force d'intensité (a+b+c+d) au niveau de l'isobarycentre.
    • Dans ton problème, il faudrait plus probablement calculer la force exercée par l'eau sur une petite surface de barrage, c'est-à-dire intuitivement pour "chaque point qui constitue la surface du barrage". Cette force dépend normalement la hauteur (voir ceci)
    • Cela signifie que la force résultante exercée par l'eau s'applique une fois intégrée plus bas que le centre de gravité (puisque la force exercée par l'eau est plus forte au bas du barrage). Appelons ce point (appelé centre de poussée) G'. L'approximer par G revient à implicitement déplacer la force appliquée en G' vers G et ignorer le moment induit par ce changement de point d'application (je te laisse voir un cours de mécanique, par exemple sur les torseurs) : ce moment est obtenu en calculant le produit vectoriel GG' ^ R où R désigne le vecteur force résultante appliquée en G'.
    • Tu peux, au lieu de décomposer de manière continue la force exercée par l'eau et l'intégrer considérer la force exercée à chaque point de ton maillage et déduire le barycentre à partir des points du maillage. Toutefois ça reste une approximation discrète d'un problème que tu peux normalement résoudre de manière continue.

    Bonne chance

    1
    1. Contributeur

      Attention, comme déjà écrit, il ne cherche par le barycentre des 4 points, mais le barycentre du polygone formé par ces 4 points.

      0
    2. Modérateur
      @yg_be

      Comme je l'expliquais, dans le cas d'un polygone non convexe l'isobarycentre n'est en général pas le centre de gravité (notamment quand le polygone n'est pas convexe). Donc dans le cas général voir ce lien.

      0
    3. Contributeur
      @mamiemando

      Le code python en #21 calcule le centre de gravité des 4 points, tandis qu'il cherche le centre de masse de la surface du polygone formé par ces 4 points.

      0
    4. Modérateur
      @yg_be

      J'ai bien compris yg_be, et c'est pour ça que j'ai donné dans le message #27 ce lien (qui renvoie sur ce paragraphe wikipedia), qui lui répond à la question du centre de gravité pour un polygone.

      0
  4. Dans les règles que j'ai portée à ton intention, il y a notamment 

    • Présentez le travail déjà tenté ou expliquez les réflexions menées, cela donnera aux personnes qui essayerons de vous aider une base pour vous corriger ou vous réorienter. Mais aussi cela évitera d'obtenir une réponse utilisant des outils ou des concepts que vous n'auriez pas encore appris et donc que cette réponse ne soit pas utile, voire apporte encore plus de confusion.
    • Si votre demande concerne la programmation, postez votre code en utilisant la coloration syntaxique. Si un message d'erreur apparait, recopiez-le en intégralité, précisez la ligne où il apparait et le contenu des variables.

    0
    1. Bonjour Mariam, oui c’est cela. 

      Pour être plus clair j’ai modélisé un barrage sur python et j’aimerai maintenant trouver le barycentre de ce barrage afin d’y appliquer son poids. 

      0
      1. Puisque tu as dû écrire pendant que je postais ma réponse, cf message 5.

        Cela dit, si tu es capable de modéliser un barrage, calculer un barycentre devrait être une formalité 

        0
      2. Contributeur

        bonjour, 4 points, c'est peu pour définir un barrage.

        1
      3. Contributeur

        quand tu écris "poids", cela inclut-il toutes les forces exercées sur le barrage, ou uniquement son poids?

        0
    2. Bonjour,

      Tu ne dis pas si les 4 points sont dans le plan (2D) ou dans l'espace (3D)

      Bref si chacun des 4 points a des coordonnées X,Y ou bien X,Y,Z

      A part ça, c'est vrai qu'avec les coordonnées des points, c'est très simple

      0
      1. j’ai modéliser le barrage à l’aide de deux listes x et y que j’ai tracé ensuite avec un plt et ensuite j’ai maillé ce barrage avec un programme mailleur donné par le professeur en élément fini. Une fois cette image sortie, j’aimerai trouver à l’aide des coordonnés de 4 points du barrage dans un plan 2D tracer le point du barycentre et y appliquer la poids totak du barrage. 

        0
      2. Contributeur
        @peuzdubinks

        Je ne suis pas certain qu'une représentation en 2D a du sens pour un barrage.

        Comment sélectionnes-tu ces 4 points?

        Montre nous ton code et tes données.  Je me demande si le plus logique n'est pas de calculer la moyenne des nœuds de la maille.

        0
      3. @yg_be
        # -*- coding: utf-8 -*-
        """
        Created on Thu Dec  8 08:15:46 2022
        
        @author: Pierre
        """
        
        #importation des bibliothèque
        # import numpy as np
        # import matplotlib.pyplot as plt
        # from mailleur import maillage
        
        # -*- coding: utf-8 -*-
        """
        Created on Thu Dec  8 08:12:05 2022
        
        @author: Pierre
        """
        
        
        import numpy as np
        import matplotlib.pyplot as plt
        from mailleur import maillage 
        
        
        #propriété des matériaux
        EBeton = 50e9
        nuBeton = 0.25
        rhoBeton = 2500
        ESol = 100e6
        nusol = 0.35
        rhoSol = 1500
        rhoW = 1000
        g = 9.81
        
        
        N = 80
        #géométrie du projet
        xmin, xmax = 0, 30
        ymin, ymax = -10, 10
        H, L, Ltop = 10, 6, 1
        
        #position barrage
        xb0 = 10
        yb0 = 0
        
        #définition des caractérisitiques du sol
        Kx=1E-5 
        Kz=1E-5 
        
        #définition du nombre de noeuds
        fact1 = 5
        Nx=7*fact1 
        Ny=5*fact1
        
        N = 30
        #taille des mailles
        dX= xmax/ (Nx-1)
        dY= ymax/ (Ny-1)
        
        #Limites horizontales du barrage
        i1 = round(xb0/dX)
        i2 = round((xb0+L+Ltop)/dX)
        
        #Limites horizontales du barrage
        j1 = round(yb0/dY)
        
        #frontières & maillage en éléments finis
        
        x = np.array([xmin, xmin,xb0, xb0, xb0+Ltop, xb0+Ltop+L, xmax, xmax])
        y = np.array([ymin, yb0, yb0, yb0+H, yb0+H,yb0,yb0, ymin])
        xNode, yNode, connect, tri = maillage(x, y, N)
        
        
        plt.figure(2)
        plt.triplot(xNode, yNode, connect)
        
        #tracé du contour du problème et des noeuds
        xn1D=np.array(list(range(Nx)))*dX
        yn1D=np.array(list(range(Ny)))*(-dY)
        [Xnode, Ynode]=np.meshgrid(xn1D,yn1D)
        
        
        plt.figure(num=1, figsize=(10, 6))
        plt.clf()
        plt.plot(x,y,'b--')
        plt.xlabel('X (m)')
        plt.ylabel('Z(m)')
        plt.show()
        
        
        #Remplissage de la matrice A et du vecteur B avec les bonnes expressions
        #Initialisation de la matrice et du second membre à 0
        A = np.zeros([Nx*Ny,Nx*Ny]) 
        B = np.zeros([Nx*Ny,1]) 
        
        H2 = ymin
        Kx=1E-5 
        Kz=1E-5 
        
        #Balayage de l'ensemble des noeuds du maillage
        for i in range(Nx):
            for j in range(Ny):
             #Calcul de l'indice k correspond au couple (i,j) courant
                k = (i) + Nx*(j) 
                     # Série de tests permettant d'affecter à chaque noeud l'équation qui lui correspond dans la matrice et le 2nd membre
                if j==0 and i>=i2: # condition en charge à droite du barrage
                    A[k,k] = 1
                    B[k]   = 0
                elif j==j1 and i<=i1: # condition en charge en aval
                    A[k,k] = 1
                    B[k]   = H2
                elif i==0 and j>j1 and j<(Ny-1): # condition aux limites à gauche du domaine (symétrie)
                    A[k,k]   =  -1
                    A[k, k+1] = 1
                    B[k]   =  0
                elif i==(Nx-1) and j>0 and j<(Ny-1):  # condition aux limites à droite du domaine (infini)
                    A[k,k]   =  1
                    A[k, k-1] = -1
                    B[k] = 0            
                elif j==(Ny-1):   # condition aux limites en bas du domaine (substratum imperméable)
                    A[k,k] = 1
                    A[k, k-Nx] = -1
                    B[k] = 0
                elif i>i1 and i<i2 and j==j1:  # condition sous le barrage
                    A[k,k] = 1
                    A[k, k+Nx] = -1
                    B[k] = 0
                else:  # Points dans le domaine : on se sert des 4 voisins
                    A[k,k] = -2*((Kz/dX**2)+(Kz/dY**2))
                    A[k, k-1] = (Kx/(dX**2))
                    A[k,k+1] = (Kx/(dX**2))
                    A[k,k-Nx] = (Kz/(dY**2))
                    A[k, k+Nx] = (Kz/(dY**2))
                    B[k] = 0
        
        #resolution proprement dite
        #Resolution du Système Linéaire (méthode du pivot de Gauss inclue dans python)
        H = np.linalg.inv(A) @ B
        
        
        #Préparation de l'affichage des isocontours
        #Matrice d'affichage
        #Xplot = np.zeros([Nx,Nz])
        #Zplot = np.zeros([Nx,Nz])
        Hplot = np.zeros([Nx,Ny])
        Vx = np.zeros([Nx,Ny])
        Vz = np.zeros([Ny,Nx])
        #Vf = np.zeros([Nx,Nz])
        
        HplotT = Hplot.transpose()
        
        for i in range(Nx):
            for j in range(Ny):
                k = i + Nx*(j) 
                Hplot[i,j] = H[k]
        
                    
        HplotT = Hplot.transpose() # on repasse l'espace physique dans le bon sens 
        
        #trace type 1
        nbcolo=30
        levels = np.linspace(H2-0.5, 1, nbcolo+1)
        fig = plt.contour(Xnode, Ynode, HplotT, levels=levels, cmap='Reds')
        cbar1 = plt.colorbar()
        cbar1.set_label('pression')
        # fig = plt.contourf(HplotT, levels=levels, cmap='coolwarm')
        
        # #trace type 2
        plt.figure(num=1, figsize=(10, 6))
        plt.pcolor(Xnode, Ynode, HplotT, cmap='coolwarm', vmin=H2, vmax=0)
        cbar2 = plt.colorbar()
        cbar2.set_label('Charge hydraulique (m)')
        plt.title('Projet méthode numérique', fontsize = 20)
        plt.show()
        
        et je vous joins de plus la fonction mailleur:
        
        from shapely.geometry import Point, Polygon
        import numpy as np
        from scipy.spatial import Delaunay
        
        # import matplotlib.tri as tri
        
        # import matplotlib.pyplot as plt
        # from shapely.plotting import plot_polygon
        # import matplotlib.tri as tri
        
           
        def maillage(x,y,Nx):
        
            coords = np.zeros([len(x),2]) 
            
            for i in range(len(x)):
                coords[i,:] = np.array([x[i],y[i]])     
                
            poly = Polygon(coords)
            # plot_polygon(poly)
            # plt.show()
            
            # Generate random points
            xmin, xmax, ymin, ymax = min(x), max(x), min(y), max(y)
            dx = (xmax - xmin)/Nx
            Ny = (ymax - ymin) * Nx / (xmax - xmin)
            dy = (ymax-ymin)/Ny
            xdot = np.arange(xmin,xmax,dx)
            ydot = np.arange(ymin,ymax,dy)
            
            XX, YY = np.meshgrid(xdot, ydot)
            Z = len(xdot) * len(ydot)
            xNode=np.reshape(XX,Z)
            yNode=np.reshape(YY,Z)
            
            xN = []
            yN = []
        
            for i in range(Z):
                a = Point(xNode[i],yNode[i])
                b = poly.covers(a)
                if b:
                    xN = np.append(xN, xNode[i])
                    yN = np.append(yN, yNode[i])
            
            xyNode=np.zeros([len(xN),2])
            xyNode[:,0]=np.transpose(xN)
            xyNode[:,1]=np.transpose(yN)
            
            triang  = Delaunay(xyNode) 
            connect = triang.vertices
            
            #suppression des triangles en dehors du sol et du barrage
            xTri=np.mean(xN[connect],axis=1)
            yTri=np.mean(yN[connect],axis=1)
            
            con = []
            for i in range(len(connect)):
                ac = Point(xTri[i],yTri[i])
                bc = poly.covers(ac)
                if bc:
                    con = np.append(con, i)
            
            con = np.array(con, dtype='int')
            connect = connect[con,:]        
            
            # #triangles au-dessus du sol et du barrage à supprimer
            # ibad=np.where(((xTri<0)&(yTri>0))|((xTri>((L+Ltop)-yTri*L/H))&(yTri>0)))
            
            # xybad=np.array([xTri[ibad],yTri[ibad]])
            # isupp=tri.find_simplex(xybad.T) #indices des trangles contenant les centres à supprimer
            # connect=np.delete(connect,isupp,0)
            # #maj des coordonnées du centre des elements
            # xTri=np.mean(xNode[connect],axis=1)
            # yTri=np.mean(yNode[connect],axis=1)
            
            # triang = tri.Triangulation(xyNode[:,0], xyNode[:,1])
            # connect = triang.get_masked_triangles()
            
            # # Mask off unwanted triangles.
            # min_aire = dx*dy
            
            # con = []
            # for i in range(len(connect)):
            #     [no1,no2,no3] = xyNode[connect[i],:]
            #     vec12 = np.array([no2[0]-no1[0],no2[1]-no1[1]])
            #     vec13 = np.array([no3[0]-no1[0],no3[1]-no1[1]])
            #     aire = (vec12[0] * vec13[1] - vec12[1] * vec13[0])/2 
            #     if aire <= min_aire:
            #         con = np.append(con, i)
            
            # con = np.array(con, dtype='int')
            # connect = connect[con,:]
        
            return xN, yN, connect, triang

        J'obtiens sur une figure les écoulements sur le barrage et sur une autre le maillage du barrage + sol et avec ce maillage et j'aimerais trouver le barycentre du barrage.

        0
      4. @yg_be

        Merci pour ton aide je vais essayer d'avancer !

        0