8.3. Calcul géométrique en 2D/3D#
Marc BUFFAT , Université Claude Bernard Lyon 1
%matplotlib inline
# bibliotheques de base
import matplotlib
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import rcParams
rcParams['font.family'] = 'serif'
rcParams['font.size'] = 14
8.3.1. Objectif#
8.3.1.1. Base d’un module de CAO objet#
On se propose d’écrire des fonctions Python pour manipuler des éléments 2D (triangle, rectangle, cercle, ellipse, polygones, …).
Pour cela on va créer une petite bibliothèque en Python avec des classes.
8.3.2. Analyse#
élèments de base
données
méthodes
8.3.3. Algorithmes#
- coordonnées barycentriques
- surface, intersection
8.3.4. Calcul géométrique en 2D#
8.3.4.1. classe de base Point#
Créer une classe de base (Point) dans l’espace cartésion en 2D permettant de définir des points par leurs coordonnées (X,Y). Écrire des méthodes utiles par la suite (par exemple permettant de calculer la distance entre deux points, de l’afficher dans un plan, etc.).
8.3.4.2. classe générique Polygone#
définition
class Point:
"""classe de Point en 2D"""
def __init__(self, x, y):
"""creation d'un point a partir de ces coordonnees x et y"""
self.x = x
self.y = y
return
def __str__(self):
chaine = "point x={:5.2f} y={:5.2f}".format(self.x,self.y)
return chaine
def translation(self, dx, dy):
self.x = self.x + dx
self.y = self.y + dy
return
def plot(self):
plt.plot([self.x],[self.y],'o',markersize=12)
return
# calcul distance entre 2 pts
def distance(A,B):
d = np.sqrt((B.x - A.x)**2 + (B.y - A.y)**2)
return d
# test
P = Point(13,14)
print(P)
P.translation(-5,-8)
print(P)
Q = Point(10,9)
print(distance(P,Q))
# tracer
P.plot()
Q.plot()
point x=13.00 y=14.00
point x= 8.00 y= 6.00
3.605551275463989

# Polygone
class Polygone:
def __init__(self, Lpts):
self.Lpts = Lpts
return
def __str__(self):
chaine = "polygone: {} ".format(len(self.Lpts))
for P in self.Lpts:
chaine = chaine + " , " +str(P)
return chaine
def translation(self, dx, dy):
for P in self.Lpts:
P.translation(dx,dy)
return
def plot(self):
for P in self.Lpts:
P.plot()
X = []
Y = []
for P in self.Lpts:
X.append(P.x)
Y.append(P.y)
X.append(X[0])
Y.append(Y[0])
plt.plot(X,Y)
return
A = Point(0,0)
B = Point(1,0)
C = Point(0,1)
poly1 = Polygone([A,B,C])
print(poly1)
poly1.translation(2,0)
print(poly1)
# tracer
poly1.plot()
polygone: 3 , point x= 0.00 y= 0.00 , point x= 1.00 y= 0.00 , point x= 0.00 y= 1.00
polygone: 3 , point x= 2.00 y= 0.00 , point x= 3.00 y= 0.00 , point x= 2.00 y= 1.00

class Triangle(Polygone):
def __init__(self,A,B,C):
self.Lpts = [A,B,C]
return
T1 = Triangle(A,B,C)
print(T1)
T1.translation(0,1)
print(T1)
polygone: 3 , point x= 2.00 y= 0.00 , point x= 3.00 y= 0.00 , point x= 2.00 y= 1.00
polygone: 3 , point x= 2.00 y= 1.00 , point x= 3.00 y= 1.00 , point x= 2.00 y= 2.00
type(T1),type(poly1)
(__main__.Triangle, __main__.Polygone)
8.3.4.3. cas particulier de Triangle et Quadrangle#
Dans un premier temps, pour les éléments surfaciques de type triangle et quadrangle, écrire les fonctions qui calculent :
la surface
le périmètre
Chaque élément est défini par les coordonnées de ses points, donnés dans l’ordre trigonométrique. Montrez que ces fonctions utilisent des fonctions qui calculent :
la longueur d’un segment
la norme du produit vectoriel de 2 vecteurs
8.3.4.4. Généralisation: classe Figure#
Créer une classe générique de base (figure), dont sera issue la sous-classe polygone. Créer les sous-classes ellipse et cercle avec les méthodes associées. Valider.
Généraliser les algorithmes de calcul de surface au cas d’un polygone plan quelconque. Valider.
n.b. : on supposera que le polygone est donné par une liste de noeuds orientés dans le sens trigonométrique, et on note \((U,V)\) le repère dans le plan du polygone.
pour un polygone, on va calculer la somme des aires « signées » des trapèzes formés par deux des points des segments (p1, p2) du polygone et les projections de ces deux points sur l’axe des U. Le signe sera celui du produit scalaire \((P1\wedge P2) V\)
8.3.5. Implémentation#
class Point:
""" classe de Point dans le plan """
def __init__(self,x,y):
self.x=x
self.y=y
return
def __str__(self):
s="(%g,%g)"%(self.x,self.y)
return s
def plot(self):
""" trace d'un point """
plt.plot(self.x,self.y,'o',markersize=10)
return
# distance entre 2 points
def distance(P1,P2):
""" calcul distance entre 2 points"""
d=np.sqrt((P1.x-P2.x)**2+(P1.y-P2.y)**2)
return d
class Polygone:
""" Classe figure geometrique a partir de Points"""
def __init__(self,L):
""" constructeur a partir d'une liste de points """
self.Pts=L
return
def __str__(self):
s="figure "
for P in self.Pts:
s=s+": "+str(P)
return s
def plot(self):
X=[p.x for p in self.Pts]
Y=[p.y for p in self.Pts]
X.append(X[0])
Y.append(Y[0])
plt.plot(X,Y,'-',lw=2)
for P in self.Pts:
P.plot()
return
def perimetre(self):
np=len(self.Pts)
dist=0.0;
for i in range(np-1):
dist += distance(self.Pts[i],self.Pts[i-1])
dist += distance(self.Pts[-1],self.Pts[0]);
return dist
def translate(self,x0,y0):
for P in self.Pts:
P.x += x0
P.y += y0
return
def rotate(self,x0,y0,theta):
""" rotation avec angle en degre """
angle=theta*pi/180.0;
for P in self.Pts:
x1 = x0 + (P.x-x0)*np.cos(angle)-(P.y-y0)*np.sin(angle)
y1 = y0 + (P.x-x0)*np.sin(angle)+(P.y-y0)*np.cos(angle)
P.x = x1
P.y = y1
return
# classe heritee triangle
class Triangle(Polygone):
"""Classe Triangle"""
def __init__(self,P1,P2,P3):
self.Pts=[P1,P2,P3]
return
def plot(self):
X=[p.x for p in self.Pts]
Y=[p.y for p in self.Pts]
plt.fill(X,Y,'b')
return
8.3.6. Validation#
# test
A=Point(0.,0.);
B=Point(1.,0.);
C=Point(1.,1.);
print("A:",A)
P=Polygone([A,B,C]);
T=Triangle(A,B,C)
#T=copy.deepcopy(Triangle(A,B,C))
print("P:",P)
print("perimetre ",P.perimetre())
P.translate(1,-2)
print("P:",P)
print("perimetre ",P.perimetre())
T.translate(-1,2)
print(T)
A: (0,0)
P: figure : (0,0): (1,0): (1,1)
perimetre 3.82842712474619
P: figure : (1,-2): (2,-2): (2,-1)
perimetre 3.82842712474619
figure : (0,0): (1,0): (1,1)
plt.figure(figsize=(12,10))
P.plot()
A.plot()
B.plot()
plt.axis('equal')
plt.xlim((-3,3.))
plt.ylim((-3,3.))
T.plot()
