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

  1. #1
    Membre averti
    TDGCSectionOfBeam: Une classe pour le calcul des caractéristiques d'une section droite de poutre
    Bjr à vous,

    Je vous propose ici une classe (licence CC0) pour le calcul des caractéristiques d'une section droite de poutre délimitée par un polygone fermé:

    - aire
    - périmètre
    - centre de gravité
    - moments quadratiques
    - directions principales et moments d'inertie principaux

    Ressources:
    https://en.wikipedia.org/wiki/Second_moment_of_area
    https://campus.mines-douai.fr/pluginfile.php/9832/mod_resource/content/0/Chapitre4_webLatex/co/C3_MomentsPrincipaux.html

    Représentation graphique de la section et de la position du centre de gravité


    Cercle de MOHR des inerties de la section (et non pas 'Cercle de MORT')


    La classe comporte deux unités minimales:

    - DGCTypes.pas: Types de données pour la classe précitée et bien d'autres
    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
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
     
    unit DGCTypes;
     
    {$mode delphiunicode}
     
    interface
     
    uses
      Classes, SysUtils, math, graphics;
    const DIEU_AU_CARRE = -1; // dieu étant imaginaire pur, son carré vaut -1 ;-))))
    const DGC_DEFAULT_FONT_NAME = 'Arial';
     
    type TDGCPoint2D = record
      X:  double;
      Y:  double;
    end;
    type TDGCArrayPoints2D = array of TDGCPoint2D;
    type TDGCPoint2Dh = record  // coordonnées 2D homogènes
      X:  double;
      Y:  double;
      H:  double;
    end;
    type TDGCBoundingBox = record
      X1:  double;
      Y1:  double;
      X2:  double;
      Y2:  double;
    end;
    type TDGCMatrix3x3 = array[0..2, 0..2] of double;
     
    //Elements dessinés
    type  TDGCOptions = set of (dgcoX_AXIS, dgcoY_AXIS,
                                dgcoPRI_X_GRID, dgcoPRI_Y_GRID,
                                dgcoSEC_X_GRID, dgcoSEC_Y_GRID,
                                dgcoCOORDS_RIVE_X, dgcoCOORDS_RIVE_Y
                               );
     
    //Modes de travail spécifiques
    type  TDGCModesTravail  = (mtgcsREADY,
                               mtgcsPAN_PREMIER_POINT, mtgcsPAN_SECOND_POINT,
                               mtgcsZOOM_PREMIER_COIN, mtgcsZOOM_SECOND_COIN
                              );
    // Types d'éléments de la liste d'affichage
    type TDGCTypeDessinObjet = (
                       tdoNONE,
                       tdoENTITY_SEGMENT,       // TDGCSegment
                       tdoENTITY_INFINITE_LINE, // TDGCInfiniteLine
                       tdoENTITY_RECTANGLE,     // TDGCRectangle;
                       tdoENTITY_ELLIPSE,       // TDGCEllipse
                       tdoENTITY_TRIANGLE,      // TDGCTriangle
                       tdoENTITY_POLYLINE,      // TDGCPolyline
                       tdoENTITY_POLYGONE,      // TDGCPolygon
                       tdoENTITY_CURVE,         // TDGCCurve
                       tdoENTITY_TEXT,          // TDGCText
                       tdoCMD_SET_PEN,          // TDGCPen
                       tdoCMD_SET_BRUSH,        // TDGCBrush
                       tdoCMD_SET_FONT,         // TDGCFont
                       tdoCMD_SVG_BEGIN_GROUPE,
                       tdoCMD_SVG_END_GROUPE
                       );
     
    type
     
    { TDGCDessinObjet }
     
     TDGCDessinObjet = record
      IdxGroupe      : integer;
      Name           : string;
      TypeDessinObjet: TDGCTypeDessinObjet;
      DessinObjet    : TObject;
      function GetDescroDessinObjet(): string;
    end;
    type TDGCStyleSheet = record
      Stylename        : string;
      Description      : string;
      // Crayon
      PenColor         : TColor;
      PenOpacity       : byte;
      PenStyle         : TPenStyle;
      PenWidthInPX     : byte;
      PenWidthInMM     : double;
     
      // Brosse
      BrushColor       : TColor;
      BrushOpacity     : byte;
      BrushStyle       : TBrushStyle;
     
      // Fontes
      FontName         : string;
      FontColor        : TColor; // Utiliser la couleur de Brush
      FontOpacity      : byte;
      FontSizeInPts    : integer;
      FontSizeInMM     : double;
     
      FontStyle        : TFontStyles;
    end;
     
     
    // Types internes
    type TTypeCurve = (tdgcBEZIER_CURVE, tdgcSPLINE_CURVE);
    type TInfiniteLineOrientation = (tdgcVERTICAL_LINE, tdgcHORIZONTAL_LINE);
    // Arc de courbe de Bézier
    // On stocke les tangentes ET les points de contrôle
     
    type TDGCBezierArc = record
      PT1    : TDGCPoint2D; // extremité courbe 1
      TangP1 : TDGCPoint2D; // Tangente en P1
      //PC1    : TDGCPoint2D; // Point de contrôle PC2
      PT2    : TDGCPoint2D; // extremité courbe 2
      TangP2 : TDGCPoint2D; // Tangente en P2
      //PC2    : TDGCPoint2D; // Point de contrôle PC2
    end;
     
     
    // pour les pointeurs sur fonctions de conversion
    type TFunctionGetCoordsMonde = function(const PP: TPoint): TDGCPoint2D of object;
    type TFunctionGetCoordsPlan  = function(const PM: TDGCPoint2D): TPoint of object;
    //******************************************************************************
    implementation
    uses
      DGCDummyUnit; // pour limiter le bug de 'Fin de code source non trouvée
     
     
     
    { TDGCDessinObjet }
     
    function TDGCDessinObjet.GetDescroDessinObjet(): string;
    var
      LS: TStringList;
    begin
      LS := TStringList.Create;
      try
        LS.Clear;
        LS.Add('tdoNONE');
        LS.Add('tdoENTITY_SEGMENT');
        LS.Add('tdoENTITY_INFINITE_LINE');
        LS.Add('tdoENTITY_RECTANGLE');
        LS.Add('tdoENTITY_ELLIPSE');
        LS.Add('tdoENTITY_TRIANGLE');
        LS.Add('tdoENTITY_POLYLINE');
        LS.Add('tdoENTITY_POLYGONE');
        LS.Add('tdoENTITY_CURVE');
        LS.Add('tdoENTITY_TEXT');
        LS.Add('tdoCMD_SET_PEN');
        LS.Add('tdoCMD_SET_BRUSH');
        LS.Add('tdoCMD_SET_FONT');
        LS.Add('tdoCMD_SVG_BEGIN_GROUPE');
        LS.Add('tdoCMD_SVG_END_GROUPE');
     
        Result := LS.Strings[Ord(self.TypeDessinObjet)];
      finally
        FreeAndNil(LS) ;
      end;
    end;
     
    end.


    et le fichier principal: DGCClassSectionOfBeam

    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
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
     
    unit DGCClassSectionOfBeam;
    // Calcul de caractéristiques de sections droites d'une poutre:
    // - aire
    // - centre de gravité
    // - limites
    // - moments quadratiques
    // - produits de surface
    // - directions principales
    {$mode delphiunicode}
    interface
     
    uses
      Classes, SysUtils, math,
      DGCTypes;
     
    type
     
    { TDGCSectionOfBeam }
     
     TDGCSectionOfBeam = class(TList)
      private
        FBounds    : TDGCBoundingBox;
        FPerimetre : double;
        FArea      : double;
        FCentroid  : TDGCPoint2D;
        FInertiaOx : double;
        FInertiaOy : double;
        FInertiaOxy: double;
        FInertiaPolar: double;
        FAnglePrincipalInertie: double;
        FMainInertia_I  : double;
        FMainInertia_II : double;
        procedure CalcPerimeter();
        procedure CalcArea();
        procedure CalcCentroid();
        procedure ClearListe();
        procedure CalcInertias();
      public
        function  Initialiser(): boolean;
        procedure Finaliser();
        function  GetNbVertex(): integer;
        function  AddVertex(const V: TDGCPoint2D): boolean; overload;
        function  AddVertex(const VX, VY: double): boolean; overload;
        procedure CalcBounds();
        function  GetBounds(): TDGCBoundingBox;
        function  GetVertex(const Idx: integer): TDGCPoint2D;
        function  RemoveVertex(const Idx: integer): boolean;
        procedure CalcCaracteristiques();
     
        property  Area: double read FArea;
        property  Perimeter: double read FPerimetre;
        property  Centroid: TDGCPoint2D read FCentroid;
        property  InertiaXGX: double read FInertiaOx;
        property  InertiaYGY: double read FInertiaOy;
        property  InertiaXY: double read FInertiaOxy;
        property  InertiaPolar: double read FInertiaPolar;
        property  MainAngleInertia: double read FAnglePrincipalInertie;
        property  MainInertia_I  : double read FMainInertia_I;
        property  MainInertia_II : double read FMainInertia_II;
    end;
     
    implementation
    uses
      DGCDummyUnit;
     
    // Classes utilitaires: Liste des vertex
    function TDGCSectionOfBeam.GetNbVertex(): integer;
    begin
      Result := self.Count;
    end;
     
    procedure TDGCSectionOfBeam.ClearListe();
    var
      i, Nb: Integer;
    begin
      Nb := self.Count;
      if (0 = Nb) then Exit;
      for i := 0 to Nb - 1 do
      begin
        try
          Dispose(self.Items[i]);
        except
        end;
      end;
      self.Clear();
    end;
     
     
    function TDGCSectionOfBeam.Initialiser(): boolean;
    begin
      result := false;
      try
        FArea       := 0.00;
        FPerimetre  := 0.00;
        FCentroid.X := 0.00;
        FCentroid.Y := 0.00;
        FInertiaOx  := 0.00;
        FInertiaOy  := 0.00;
        FInertiaOxy := 0.00;
        FAnglePrincipalInertie := 0.00;
        FMainInertia_I  := 0.00;
        FMainInertia_II := 0.00;
     
        self.ClearListe();
        result      := true;
      except
      end;
    end;
     
    procedure TDGCSectionOfBeam.CalcPerimeter();
    var
      i, j, n: Integer;
      V1, V2: TDGCPoint2D;
    begin
      FPerimetre := 0.00;
      n     := GetNbVertex();
      for i := 0 to n - 1 do
      begin
        j := Ifthen(n = (i+1), 0, i+1);
        V1 := GetVertex(i);
        V2 := GetVertex(j);
        FPerimetre += hypot(V2.X - V1.X, V2.Y - V1.Y);
      end;
    end;
     
    procedure TDGCSectionOfBeam.CalcArea();
    var
      n, i, j: Integer;
      V1, V2: TDGCPoint2D;
    begin
      FArea := 0.00;
      n     := GetNbVertex();
      for i := 0 to n - 1 do
      begin
        j := Ifthen(n = (i+1), 0, i+1);
        V1 := GetVertex(i);
        V2 := GetVertex(j);
        FArea += V1.X * V2.Y - V2.X * V1.Y;
      end;
      FArea:= 0.5 * Abs(FArea);
    end;
    //centre de gravité
    procedure TDGCSectionOfBeam.CalcCentroid();
    var
      Q6A: Double;
      n, i, j: Integer;
      V1, V2: TDGCPoint2D;
    begin
      if (IsZero(FArea)) then exit;
      Q6A := 1 / (6 * FArea);
      FCentroid.X := 0.00;
      FCentroid.Y := 0.00;
      n := GetNbVertex();
      for i := 0 to n - 1 do
      begin
        j  := Ifthen(n = (i+1), 0, i+1);
        V1 := GetVertex(i);
        V2 := GetVertex(j);
        FCentroid.X += (V1.X + V2.X) * (V1.X * V2.Y - V2.X * V1.Y);
        FCentroid.Y += (V1.Y + V2.Y) * (V1.X * V2.Y - V2.X * V1.Y);
      end;
      FCentroid.X := Q6A * FCentroid.X;
      FCentroid.Y := Q6A * FCentroid.Y;
    end;
    // calcul des moments quadratiques
    procedure TDGCSectionOfBeam.CalcInertias();
    var
      V1, V2: TDGCPoint2D;
      WU: Double;
      n, i, j: Integer;
      Q1, Q2 : double;
    begin
      if (IsZero(FArea)) then exit;
      FInertiaOx  := 0.00;
      FInertiaOy  := 0.00;
      FInertiaOxy := 0.00;
      n := GetNbVertex();
      for i := 0 to n - 1 do
      begin
        j := Ifthen(n = (i+1), 0, i+1);
        V1 := GetVertex(i);
        V2 := GetVertex(j);
        WU := (V1.X * V2.Y - V2.X * V1.Y);
        FInertiaOy  += WU * (V1.X ** 2 +  V1.X * V2.X + V2.X ** 2);
        FInertiaOx  += WU * (V1.Y ** 2 +  V1.Y * V2.Y + V2.Y ** 2);
        FInertiaOxy += WU *     (V1.X * V2.Y +
                             2 * V1.X * V1.Y +
                             2 * V2.X * V2.Y +
                                 V2.X * V1.Y);
      end;
      // moments IxOx et IyOy par rapport au repère général
      FInertiaOx  := (FInertiaOx  / 12); //- FArea * sqr(FCentroid.Y);
      FInertiaOy  := (FInertiaOy  / 12); //- FArea * sqr(FCentroid.X);
      // produit de surface
      FInertiaOxy := (FInertiaOxy / 24);
      // transport des moments vers le centroide
      // IxOx = IxGx + S.Yg ** 2, avec S: aire de la section et Yg ordonnée du CDG
      // IxGx = IxOx + S.Xg ** 2, avec S: aire de la section et Xg abscisse du CDG
      // IxGy = IxOy + S.Xg.Yg
      FInertiaOx  := FInertiaOx  - FArea * FCentroid.Y ** 2;
      FInertiaOy  := FInertiaOy  - FArea * FCentroid.X ** 2;
      FInertiaOxy := FInertiaOxy - FArea * (FCentroid.X * FCentroid.Y);
      // moment quadratique polaire: Io = IxGx + IyGy
      FInertiaPolar := FInertiaOx + FInertiaOy;
      // Moments d'inertie principaux, axes principaux
      // cf cours https://campus.mines-douai.fr/pluginfile.php/9832/mod_resource/content/0/Chapitre4_webLatex/co/C3_MomentsPrincipaux.html
      WU := FInertiaOy - FInertiaOx;
      FAnglePrincipalInertie := ifthen (IsZero(WU), 0.00, 0.50 * ArcTan(2 * FInertiaOxy / WU));
     
      Q1 := 0.50 * (FInertiaOx + FInertiaOy);
      Q2 := sqrt((0.50 * (FInertiaOx - FInertiaOy)) ** 2 + FInertiaOxy ** 2);
     
      FMainInertia_I   := Q1 - Q2;
      FMainInertia_II  := Q1 + Q2;
    end;
     
    procedure TDGCSectionOfBeam.CalcCaracteristiques();
    begin
      CalcBounds();
      CalcPerimeter();
      CalcArea();
      CalcCentroid();
      CalcInertias();
    end;
     
    procedure TDGCSectionOfBeam.Finaliser();
    begin
      self.ClearListe();
    end;
    function  TDGCSectionOfBeam.AddVertex(const V: TDGCPoint2D): boolean; overload;
    var
      pS : ^TDGCPoint2D;
    begin
      result := false;
      try
        New(pS);
        pS^ := V;
        self.Add(pS);
        Result := True;
      except
      end;
    end;
    function  TDGCSectionOfBeam.AddVertex(const VX, VY: double): boolean; overload;
    var
      EWE: TDGCPoint2D;
    begin
      EWE.X := VX; EWE.Y := VY;
      Result := AddVertex(EWE);
    end;
     
    procedure TDGCSectionOfBeam.CalcBounds();
    const INFINITEE = 1E30;
    var
      i, Nb: Integer;
      EWE: TDGCPoint2D;
    begin
      FBounds.X1 :=  INFINITEE;
      FBounds.Y1 :=  INFINITEE;
      FBounds.X2 := -INFINITEE;
      FBounds.Y2 := -INFINITEE;
      Nb := GetNbVertex();
      if (0 = Nb) then exit;
      for i := 0 to Nb - 1 do
      begin
        EWE := getVertex(i);
        if (EWE.X < FBounds.X1) then FBounds.X1 := EWE.X;
        if (EWE.Y < FBounds.Y1) then FBounds.Y1 := EWE.Y;
        if (EWE.X > FBounds.X2) then FBounds.X2 := EWE.X;
        if (EWE.Y > FBounds.Y2) then FBounds.Y2 := EWE.Y;
      end;
    end;
     
    function TDGCSectionOfBeam.GetBounds(): TDGCBoundingBox;
    begin
      result := FBounds;
    end;
     
     
    function TDGCSectionOfBeam.GetVertex(const Idx: integer): TDGCPoint2D;
    var
      pS : ^TDGCPoint2D;
    begin
      pS := self.Items[Idx];
      Result := pS^;
    end;
     
    function TDGCSectionOfBeam.RemoveVertex(const Idx: integer): boolean;
    begin
      Result := False;
      try
        Dispose(self.Items[Idx]);
      finally
        self.Delete(Idx);
        Result := True;
      end;
    end;
    end.


    Exemple d'utilisation:

    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
     
    procedure TCdrCalculette.Button1Click(Sender: TObject);
    const
      //TX = -50; TY = -100;
      TX = 0; TY = 0;
     
    var
      MySection: TDGCSectionOfBeam;
      BB: TDGCBoundingBox;
      Nb, i, QIdxStyleSheet: Integer;
      MySommet: TDGCPoint2D;
    begin
      MySection := TDGCSectionOfBeam.Create;
      try
        if (MySection.Initialiser()) then
        begin
          MySection.AddVertex(  0,   0);
          MySection.AddVertex(320,   0);
          MySection.AddVertex(320,  20);
          MySection.AddVertex( 60,  20);
          MySection.AddVertex( 60, 280);
          MySection.AddVertex(110, 280);
          MySection.AddVertex(110, 300);
          MySection.AddVertex(  0, 300);
          MySection.AddVertex(  0, 280);
          MySection.AddVertex( 50, 280);
          MySection.AddVertex( 50,  20);
          MySection.AddVertex(  0,  20);
          //*)
          MySection.CalcBounds();
          // centre de gravité, inerties, aires, etc ...
          MySection.CalcCaracteristiques();
          ListerCaracteristiquesSections(MySection);
          // dessiner la section
          DessinerSection(MySection);
          DessinerCercleDeMohr(MySection);
          MySection.Finaliser();
        end;
      finally
        FreeAndNil(MySection);
      end;
    end;           
     
    //...
      lbCentroidX.Caption       := FormatterNombreOOo(S.Centroid.X, 3);
      lbCentroidY.Caption       := FormatterNombreOOo(S.Centroid.Y, 3);
      lbAire.Caption            := FormatterNombreOOo(S.Area, 3);
      lbPerimetre.Caption       := FormatterNombreOOo(S.Perimeter, 3);
      lbIxGx.Caption            := FormatterNombreOOo(S.InertiaXGX, 3);
      lbIyGy.Caption            := FormatterNombreOOo(S.InertiaYGY, 3);
      lbIxy.Caption             := FormatterNombreOOo(S.InertiaXY, 3);
      lbAnglePrincipal.Caption  := FormatterNombreOOo(radtodeg(S.MainAngleInertia), 3);
      lbInertieI.Caption        := FormatterNombreOOo(S.MainInertia_I, 3);
      lbInertieII.Caption       := FormatterNombreOOo(S.MainInertia_II, 3);


    Pour attribution CC0.

  2. #2
    Membre éprouvé
    Intéressent
    Merci de partager ce genre d'outil. Je n'y connait strictement rien en calcul de poutre mais je vais en donner l'informatuion à un collègue ingénieur mécanicien.
    Il y a des jours où j'éprouve une haine profonde envers microsoft
    Venez vous défouler ici ou c'est amusant
    Mon modeste site et mes modestes oeuvres sont
    Rémi

###raw>template_hook.ano_emploi###