Equation normale de la droite orientée 2D

Soyez le premier à donner votre avis sur cette source.

Vue 14 fois - Téléchargée 3 fois

Description

Bonjour,

En essayant d'introduire les arrondis dans la série "Section: Polygone", je suis tombé sur un exemple de géométrie analytique intéressant:
Trouver le centre d'un arrondi placé sur l'angle formé de deux (segments de) droites.
Montrons que cela peut se faire "assez simplement" en expriment les droites 2D à l'aide de l'équation normale.
 

Equation normale de la droite orientée 2D

   c·x + s·y = d   (avec c² + s² = 1)

Pour tester les formules proposées, nous allons faire quelques calculs numériques avec la droite qui figure sur l'image de capture: où c=0.8, s=0.6, d=5.
   0.8·x + 0.6·y = 5

Point d'intersection avec l'axe X (y=0):   x = d/c   (c ≠ 0)
   0.8·x + 0.6·0 = 5 ==> x = d/c = 5/0.8 = 6.25

Point d'intersection avec l'axe Y (x=0):   y = d/s   (s ≠ 0)
   0.8·0 + 0.6·y = 5 ==> y = d/s = 5/0.6 = 8.33333

La droite passe donc par les points (6.25,0) et (0,8.33333).

Distance D du point (X,Y) à la droite:   D = d - c·X - s·Y
Exemples
 a) (X,Y)=(0,0):   D = 5 - 0.8·0 - 0.6·0 = 5
 b) (X,Y)=(6.25,0):   D = 5 - 0.8·6.25 - 0.6·0 = 0
 c) (X,Y)=(0,8.33333):   D = 5 - 0.8·0 - 0.6·8.33333 = 0
 d) (X,Y)=(4,3):   D = 5 - 0.8·4 - 0.6·3 = 0
 e) (X,Y)=(8,6):   D = 5 - 0.8·8 - 0.6·6 = -5
 f) (X,Y)=(5,7):   D = 5 - 0.8·5 - 0.6·7 = -3.2

Le point (X,Y) appartient à la droite:   d = c·X + s·Y

Droite orientée d'angle α et passant par le point (X,Y):
   c = sin(α)
   s = -cos(α)
   (X,Y) ‎∈ droite   ==>   d = c·X + s·Y


Projection (Xₚ,Yₚ) du point (X,Y) sur la droite:   Xₚ = X + c·D; Yₚ = Y + s·D
 a) (X,Y)=(0,0), D=5: Xₚ = 0 + c·D = 0.8·5 = 4; Yₚ = 0 + s·D = 0.6·5 = 3
 … faites les calculs
 f) (X,Y)=(5,7), D = -3.2: Xₚ = 5 - 0.8·3.2 = 2.44; Yₚ = 7 - 0.6·3.2 = 5.08
     Le point (2.44,5.08) est bien sur la droite: 5 = 0.8·2.44 + 0.6·5.08

Equation paramétrique de la droite orientée:
De l'image de capture, on tire aisément
   x = c·d - s·k
   y = s·d + c·k

Par exemple, pour l'intersection de la droite avec l'axe X:
     x = 0   ==>   k = c·d/s   ==>   y = s·d + c·c·d/s = d·(s² + c²)/s = d/s

Convention de l'orientation:
L'orientation de la droite est donnée par l'accroissement du paramètre k.
Si d>0, l'origine (0,0) est à gauche de la droite orientée.
Si d<0, l'origine (0,0) est à droite de la droite orientée.

Droite orientée passant par deux points (X₁,Y₁), (X₂,Y₂):
Soit Δ la distance entre ces points: Δ = √[(X₂-X₁)² + (Y₂-Y₁)²]
   c = (Y₂-Y₁)/Δ
   s = -(X₂-X₁)/Δ = (X₁-X₂)/Δ
   (X₁,Y₁), (X₂,Y₂) ‎∈ droite   ==>   d = c·X₁ + s·Y₁ = c·X₂ + s·Y₂


Exemple 1) (X₁,Y₁) = (6.25,0) et (X₂,Y₂) = (0,8.33333…) (intersections avec les axes):
   Δ = √[(X₂-X₁)² + (Y₂-Y₁)²] = √[(-6.25)² + 8.33333…²] = 10.416664…
   c = (Y₂-Y₁)/Δ = 8.33333…/10.416664… = 0.8
   s = (X₁-X₂)/Δ = 6.25/10.416664… = 0.6
   d = c·X₁ + s·Y₁ = 0.8·6.25 + 0.6·0 = 5
   d = c·X₂ + s·Y₂ = 0.8·0 + 0.6·8.33333… = 5

Exemple 2) (X₁,Y₁) = (10,-5) et (X₂,Y₂) = (-2,11):
   Δ = √[(X₂-X₁)² + (Y₂-Y₁)²] = √[(-12)² + 16²] = 20
   c = (Y₂-Y₁)/Δ = 16/20 = 0.8
   s = (X₁-X₂)/Δ = 12/20 = 0.6
   d = c·X₁ + s·Y₁ = 0.8·10 + 0.6·(-5) = 8 - 3 = 5
   d = c·X₂ + s·Y₂ = 0.8·(-2) + 0.6·11 = -1.6 + 6.6 = 5

Point d'intersection (X,Y) de deux droites
Utilisons les équations paramétriques:
   (X,Y) ‎∈ droite 1:   d₁ = cᵤ·X + sᵤ·Y   ==>   X = (d₁ - sᵤ·Y)/cᵤ ; Y = (d₁ - cᵤ·X)/sᵤ
   (X,Y) ‎∈ droite 2:   d₂ = cᵥ·X + sᵥ·Y   ==>   X = (d₂ - sᵥ·Y)/cᵥ ; Y = (d₂ - cᵥ·X)/sᵥ
   sᵥ·(d₁ - cᵤ·X) = sᵤ·(d₂ - cᵥ·X)   ==>   sᵥ·d₁ - sᵤ·d₂ = (sᵥ·cᵤ - sᵤ·cᵥ)·X
   X = (sᵥ·d₁ - sᵤ·d₂)/(sᵥ·cᵤ - sᵤ·cᵥ)
   cᵥ·(d₁ - sᵤ·Y) = cᵤ·(d₂ - sᵥ·Y)   ==>   cᵥ·d₁ - cᵤ·d₂ = (sᵤ·cᵥ - sᵥ·cᵤ)·Y
   Y = (cᵤ·d₂ - cᵥ·d₁)/(sᵥ·cᵤ - sᵤ·cᵥ)

De la formule bien connue sin(v-u) = sin(v)·cos(u) - cos(v)·sin(u), on tire que le dénominateur q = sᵥ·cᵤ - sᵤ·cᵥ correspond au sinus de la différence des angles, qui est nul pour des droites parallèles ou antiparallèles.

Centre d'arrondi d'un angle formé de deux droites u et v
Déterminons le centre d'arrondi (X,Y) qui se trouve à la distance (±) R de chaque droite:
   R = dᵤ - cᵤ·X - sᵤ·Y   ==>   Y = (dᵤ - cᵤ·X - R)/sᵤ ; X = (dᵤ - sᵤ·Y - R)/cᵤ
   R = dᵥ - cᵥ·X - sᵥ·Y =
          dᵥ - cᵥ·X - sᵥ·(dᵤ - cᵤ·X - R)/sᵤ = dᵥ - cᵥ·(dᵤ - sᵤ·Y - R)/cᵤ - sᵥ·Y)
En posant   q = sᵥ·cᵤ - sᵤ·cᵥ   , on obtient:
   X = ((sᵤ - sᵥ)·R + sᵥ·dᵤ - sᵤ·dᵥ)/q
   Y = ((cᵤ - cᵥ)·R + cᵥ·dᵤ - cᵤ·dᵥ)/q

Nous constatons que le rayon R doit être pris négativement (centre à droite des droites orientées) si la différence des angles est négative, c'est-à-dire si le sinus q de cette différence est négatif.
 

Code de l'objet Droite2D

//// Droite2D.h
#include <math.h>
#include <stdio.h>

struct Droite2D {
  double c, s, d;

  Droite2D(const double x, const double y, const double a) {
    c = sin(a); s = -cos(a); d = c*x + s*y;
  } // passant par le point (x,y) et d'angle a

  Droite2D(const double X1, const double Y1, const double X2, const double Y2) {
    double Dx = X2 - X1, Dy = Y2 - Y1, D = sqrt(Dx*Dx + Dy*Dy);
    c = Dy/D; s = -Dx/D; d = c*X1 + s*Y1;
  } // passant par les deux points différents (X1,Y1) et (X2,Y2)

  double Angle() {return atan2(c, -s);} // en rad

  double Distance(const double X, const double Y) {return d - c*X - s*Y;}

  double IntersectionAxeX() {return d/c;} // y = 0

  double IntersectionAxeY() {return d/s;} // x = 0

  void Projection(const double X, const double Y, double *Xp, double *Yp) {
    double D = Distance(X, Y);
    *Xp = X + c*D; *Yp = Y + s*D;
  } // projection du point (X,Y)

  void Intersection(const Droite2D *dr, double *Xi, double *Yi) {
    double q = dr->s*c -s*dr->c; // sinus de la différence des angles
    *Xi = (dr->s*d - s*dr->d)/q; *Yi = (c*dr->d - dr->c*d)/q;
  } // droites non parallèles: q != 0

  void CentreArrondi(const Droite2D *dr, double R, double *Xc, double *Yc) {
    double q = dr->s*c - s*dr->c; // sinus de la différence des angles
    if (q < 0.0) R = -R;
    *Xc = ((s - dr->s)*R + dr->s*d - s*dr->d)/q;
    *Yc = -((c - dr->c)*R + dr->c*d - c*dr->d)/q;
  } // droites non parallèles: q != 0

  void Print(char *z) {
    double x, y;
    Projection(0, 0, &x, &y);
    printf("Droite2D %s: c = %8.3f ; s = %8.3f ; d = %8.3f"
      "n   Point proche: (%8.3f,%8.3f) ; Angle: %8.3f rad =%8.3f degre"
      "n   Points sur axes: (%8.3f,0) ; (0,%8.3f)n", z, c , s, d, x, y
      , Angle(), Angle()/RadParDeg, IntersectionAxeX(), IntersectionAxeY());
  }
};

 

Exemple et résultats

#include <windows.h>
const double RadParDeg = 0.01745329251994329577;
#include "Droite2D.h"
void main() {
  double X, Y, AX = 5, AY = -1, BX = 8, BY = 6, CX = 1, CY = 4, R = 1.5;
  Droite2D D = Droite2D(AX, AY, RadParDeg*120);
  D.Print("D"); printf("n");

  Droite2D u = Droite2D(AX, AY, BX, BY), v = Droite2D(BX, BY, CX, CY);
  u.Print("u"); v.Print("v");
  u.Intersection(&v, &X, &Y);
  printf("Point d'intersection u^v: (%8.3f,%8.3f)n", X, Y);
  u.CentreArrondi(&v, R, &X, &Y);
  printf("Centre d'arrondi: (%8.3f,%8.3f)nn", X, Y);

  u = Droite2D(AX, AY, CX, CY), v = Droite2D(CX, CY, BX, BY);
  u.Print("u"); v.Print("v");
  u.Intersection(&v, &X, &Y);
  printf("Point d'intersection u^v: (%8.3f,%8.3f)n", X, Y);
  u.CentreArrondi(&v, R, &X, &Y);
  printf("Centre d'arrondi: (%8.3f,%8.3f)nn", X, Y);

  u = Droite2D(CX, CY, AX, AY), v = Droite2D(AX, AY, BX, BY);
  u.Print("u"); v.Print("v");
  u.Intersection(&v, &X, &Y);
  printf("Point d'intersection u^v: (%8.3f,%8.3f)n", X, Y);
  u.CentreArrondi(&v, R, &X, &Y);
  printf("Centre d'arrondi: (%8.3f,%8.3f)n", X, Y);
  getchar();
}

Résultats:
Droite2D D: c =    0.866 ; s =    0.500 ; d =    3.830
   Point proche: (   3.317,   1.915) ; Angle:    2.094 rad = 120.000 degre
   Points sur axes: (   4.423,0) ; (0,   7.660)

Droite2D u: c =    0.919 ; s =   -0.394 ; d =    4.990
   Point proche: (   4.586,  -1.966) ; Angle:    1.166 rad =  66.801 degre
   Points sur axes: (   5.429,0) ; (0, -12.667)
Droite2D v: c =   -0.275 ; s =    0.962 ; d =    3.571
   Point proche: (  -0.981,   3.434) ; Angle:   -2.863 rad =-164.055 degre
   Points sur axes: ( -13.000,0) ; (0,   3.714)
Point d'intersection u^v: (   8.000,   6.000)
Centre d'arrondi: (   5.378,   3.691)

Droite2D u: c =    0.781 ; s =    0.625 ; d =    3.280
   Point proche: (   2.561,   2.049) ; Angle:    2.246 rad = 128.660 degre
   Points sur axes: (   4.200,0) ; (0,   5.250)
Droite2D v: c =    0.275 ; s =   -0.962 ; d =   -3.571
   Point proche: (  -0.981,   3.434) ; Angle:    0.278 rad =  15.945 degre
   Points sur axes: ( -13.000,0) ; (0,   3.714)
Point d'intersection u^v: (   1.000,   4.000)
Centre d'arrondi: (   3.579,   3.177)

Droite2D u: c =   -0.781 ; s =   -0.625 ; d =   -3.280
   Point proche: (   2.561,   2.049) ; Angle:   -0.896 rad = -51.340 degre
   Points sur axes: (   4.200,0) ; (0,   5.250)
Droite2D v: c =    0.919 ; s =   -0.394 ; d =    4.990
   Point proche: (   4.586,  -1.966) ; Angle:    1.166 rad =  66.801 degre
   Points sur axes: (   5.429,0) ; (0, -12.667)
Point d'intersection u^v: (   5.000,  -1.000)
Centre d'arrondi: (   4.607,   1.892)

Faites un croquis pour vérifier ces résultats !

Ce développement sera utilisé dans mon prochain article:
    Section_I: Polygone avec arrondis
 
 
Bonne lecture ...
 

Liens

WikidédiA: Équation de droite
WikidédiA: Équation normale
WikidédiA: Géométrie analytique
Géométrie "analytique" plan métrique (pdf)
 

Codes Sources

A voir également

Ajouter un commentaire

Commentaires

Commenter la réponse de William VOIROL

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.