Section_B: Polygone en cycle de segments

Description

[Version avec image de capture qui remplace celle du 10.02.2018]

Bonjour,

Le polygone s'adapte très bien à la notion de cycle, puisqu'il s'apparente à une "liste simplement chaînée fermée" de segments.
Pour le débutant, la programmation avec "chaînage" peut sembler plus compliquée à cause de la notion de "pointeur".
Par contre, elle permet d'ajouter et d'éliminer des éléments du cycle (ici des segments) de manière plus efficace et élégante.

Introduisons d'abord l'objet Segment:
struct Segment {  // segment de droite
  Segment *nxt=0;
  double X,Y; // point d'arrivée;

  Segment(double x,double y) {X=x; Y=y;} // constructeur

  void Translate(double dx,double dy) {X+=dx; Y+=dy;}

  void Rotate90() {double x=X; X=-Y; Y=x;}
};
utilisé par l'objet Polygone adapté au "cycle":
struct Polygone { // Basé sur des cycles de segments
  Segment *last=0;
  double A;     // Aire: A=∫dA
  double Sx,Sy; // Moments statiques: Sx=∫y·dA, Sy=∫x·dA
  double Xg,Yg; // Centre de gravité: Xg=Sy/A, Yg=Sx/A
  double Ix,Iy; // Moments d'inertie axiaux: Ix=∫y²·dA, Iy=∫x²·dA
                // Moment d'inertie polaire: Ip=Ix+Iy

  uint NbrSegments() {uint n=0;
    Segment *s=last;
    if (s) do {s=s->nxt; n++;} while (s!=last);
    return n;
  }
  void Clear() {
    Segment *p,*s=last;
    if (s) do {p=s; s=s->nxt; delete p;} while (s!=last);
    last=0;
  };
  void Append(Segment *s) { // s->nxt==0: pas encore inséré
    if (last) {s->nxt=last->nxt; last->nxt=s;} else s->nxt=s;
    last=s; // Append correspond à "InsertLast"
  }
  void Translate(double dx,double dy) {
    Segment *s=last;
    if (s) do {s=s->nxt; s->Translate(dx,dy);} while (s!=last);
  }
  void Rotate90() {
    Segment *s=last;
    if (s) do {s=s->nxt; s->Rotate90();} while (s!=last);
  }
  void CalculSeg(double xx,double yy,double x,double y) {
    double sx=x+xx,sy=y+yy,pv=xx*y-yy*x;
    A+=pv;  Sx+=pv*sy; Sy+=pv*sx; // 2*A, 6*Sx, 6*Sy
    Ix+=pv*(yy*yy+sy*y); Iy+=pv*(xx*xx+sx*x); // 12*Ix, 12*Iy
  }
  void Calcul() {
    A=Sx=Sy=Ix=Iy=0;
    Segment *s=last;
    if (s) {
      double xx=s->X,yy=s->Y,x,y;
      do {s=s->nxt;
        x=s->X; y=s->Y; CalculSeg(xx,yy,x,y); xx=x; yy=y;
      } while (s!=last);
    }
    if (A) {A/=2; Sx/=6; Sy/=6; Xg=Sy/A; Yg=Sx/A; Ix/=12; Iy/=12;}
  }
  void Write(Edit *edit) {
    char s[256];
    sprintf_s(s,"A   =%15.3frnSx  =%15.3frnSy  =%15.3frnXg  =%15.3frn"
      "Yg  =%15.3frnIx  =%15.3frnIy  =%15.3frnIp  =%15.3frn"
      ,A,Sx,Sy,Xg,Yg,Ix,Iy,Ix+Iy);
    edit->ClearWrite(s);  edit->SelectAll();
  }
  void WriteCoords(Edit *edit) {
    std::string str;
    Segment *s=last;
    if (s) do {s=s->nxt;
      char z[64]; sprintf_s(z,"$ %9.3f %9.3frn",s->X,s->Y);
      str.append(z);
    } while (s!=last);
    edit->ClearWrite(&str[0]); edit->SelectAll();
  }
  void Paint(HDC dc) {
    if (last==0) return;
    POINT *xy=new POINT[NbrSegments()];
    Segment *s=last;
    uint n=0;
    do {s=s->nxt;
      xy[n].x=Xo+(int)(s->X*Dil); xy[n].y=Yo-(int)(s->Y*Dil); n++;
    } while (s!=last);
    Polygon(dc,xy,n);
    delete xy;
  }
  void ReadCoords(Edit *edit) {Clear();
    uint k=(uint)SendMessage(edit->ed,WM_GETTEXTLENGTH,0,0);
    char *z=new char[k+1]; GetWindowText(edit->ed,z,k+1);
    double x,y;
    for (uint i=0; i<k; ++i) {
      if (z[i++]=='$') {
        sscanf_s(z+i," %lf %lf",&x,&y); Append(new Segment(x,y));
        while ((i<k)&&(z[i]!='n')) ++i;
      }
    } delete z;
  }
  void Limits(double *xinf,double *xsup,double *yinf,double *ysup) {
    *xinf=*yinf=1.7E300; *xsup=*ysup=-1.7E300;
    Segment *s=last;
    if (s) do {s=s->nxt;
      if (s->X<*xinf) *xinf=s->X; else if (s->X>*xsup) *xsup=s->X;
      if (s->Y<*yinf) *yinf=s->Y; else if (s->Y>*ysup) *ysup=s->Y;
    } while (s!=last);
  }
// --- Constructions ----------------------------------------------------------
  void Rectangle(double dx,double dy) {Clear();
    Append(new Segment(0,0)); Append(new Segment(dx,0));
    Append(new Segment(dx,dy)); Append(new Segment(0,dy));
  }
  void DemiParabole(double b,double h,uint n) {Clear();
    double a=h/b/b,dx=b/n,x=0; // demi-parabole remplacée par n segments de droite
    for (uint i=0; i<=n; ++i,x+=dx) Append(new Segment(x,a*x*x));
    Append(new Segment(0,h));
  }
};

La construction DemiParabole est proposée ici pour disposer d'un test sévère, dont le contrôle (à la main) est relativement facile.
Pour afficher le polygone en question (où l'arc de parabole est approximé par 1000 petits segments de droite), lancez le programme ou alors visualisez le fichier Capture.jpg du Zip:
On a y = (h/b²)·x² ou x = (b/√h)·√y, et posons b = 210, h = 150:

A =∫dA=[x:0→b]∫(h-y)·dx=[x:0→b]∫(h-(h/b²)·x²)·dx=[x:0→b](h·x-(h/b²/3)·x³
  =h·b-h·b/3=(2/3)·h·b=21000  (calcul: 20999.995)

Sx=∫y·dA=[y:0→h]∫x·y·dy=[y:0→h]∫(b/√h)·√y·y·dy=[y:0→h](2/5)(b/√h)·√y·y²
  =(2/5)·(b/√h)·√h·h²=(2/5)·b·h²=1890000  (calcul: 1889999.737)

Sy=∫x·dA=[x:0→b]∫x·(h-y)·dx=[x:0→b]∫(h·x-(h/b²)·x³)·dx=[x:0→b]((h/2)·x²-(h/b²/4)·x⁴
  =(1/2)·h·b²-(1/4)·h·b²=(1/4)·h·b²=1653750  (calcul: 1653749.449)

Ix=∫y²·dA=[y:0→h]∫x·y²·dy=[y:0→h]∫(b/√h)·√y·y²·dy=[y:0→h](2/7)(b/√h)·√y·y³
  =(2/7)·(b/√h)·√h·h³=(2/7)·b·h³=202500000  (calcul: 202499976.375)

Iy=∫x·dA=[x:0→b]∫x²·(h-y)·dx=[x:0→b]∫(h·x²-(h/b²)·x⁴)·dx=[x:0→b]((h/3)·x³-(h/b²/5)·x⁵
  =(1/3)·h·b³-(1/5)·h·b³=(2/15)·h·b³=185220000  (calcul: 185219922.825)

Avec la page du fichier Ixy.jpg du Zip (qui d'ailleurs confirme les formules développées ci-dessus), contrôlons encore les calculs après avoir centré la section:
Ix'=(8/175)·b·h³=32400000  (calcul: 32399981.100)

Iy'=(19/480)·h·b³=54987187.5  (calcul: 54987164.589)
Tous les calculs sont satisfaisants !

Bonne lecture ...

Liens

WikipédiA: Liste chaînée, cycle
CodeS-SourceS: Polygones
WikipédiA: Moment quadratique
Area Moment of Inertias & Centroids (pdf)
Caractéristiques géométriques des sections planes
FORMULES de PHYSIQUE

Codes Sources

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.