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/plugin...rincipaux.html

Représentation graphique de la section et de la position du centre de gravité
Nom : TDGCSectionOfBeam_Class_1.png
Affichages : 266
Taille : 71,1 Ko

Cercle de MOHR des inerties de la section (et non pas 'Cercle de MORT')
Nom : TDGCSectionOfBeam_Class_2.png
Affichages : 232
Taille : 101,0 Ko

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.