:orphan: .. _TP3_GBM3A: TP3: geométrie (POO) ==================== Classe `Vector` --------------- Écrivez un module `geometry.py` contenant une classe `Vector`, représentant un vecteur à *N=3* dimensions de coordonnées *x, y, z*. La classe devra implémenter les attributs et méthodes suivantes: * l'initialisation par ses coordonnées cartésiennes *x, y, z* (stockées en `float`), >>> v1 = Vector(3, 4, 12) * l'accès et la modification des composantes du vecteur: >>> v1.y 4.0 * la représentation en chaîne de caractères (`__repr__`) >>> print(v1) Vector(3.0, 4.0, 12.0) * une méthode `norme` (et `__abs__`) permettant d'obtenir la norme >>> v1.norme() 13.0 >>> abs(v1) 13.0 * l'addition (`__add__`) et la soustraction (`__sub__`) de deux vecteurs: >>> v2 = Vector(12, 3, 4) >>> v1 + v2 Vector(15.0, 7.0, 16.0) >>> v1 - v2 Vector(-9.0, 1.0, 8.0) * le produit (`__mul__`) de deux vecteurs, ou d'un vecteur et d'un scalaire. >>> v1 * v2 96 >>> v1 * 4 Vector(12.0, 16.0, 48.0) >>> 4 * v1 Vector(12.0, 16.0, 48.0) .. tip:: dans la méthode `__mul__(self, other)`, distinguer les cas où `other` est un vecteur (`isinstance(other, Vector)`) ou non. .. tip:: la méthode `__mul__(self, other)` ne renseigne que sur l'opération `self * other`. Pour supporter l'opération `other * self`, il faut implémenter la méthode `__rmul__`. * le produit vectoriel (`__xor__`) de deux vecteurs: >>> v1 ^ v2 Vector(-20.0, 132.0, -39.0) **N.B.** Testez votre code, par exemple en important votre module dans un autre fichier dans lequel vous vérifierez, au moins, que les exemples ci-dessus sont respectés. Attention également à lever vos propres exceptions si les opérations demandées ne sont pas autorisées d'un point de vue mathématique. Vérifiez p.ex. que votre classe refuse les opérations avec une liste. .. note:: *Après* avoir terminé l'exercice, vous pouvez aller lire l'implémentation des vecteurs :class:`turtle.Vec2D` dans la librairie :mod:`turtle`. Classe `Point` -------------- Ajoutez à votre module une classe `Point`, représentant un point à *N=3* dimensions ce coordonnées *x, y, z*, avec les méthodes suivantes: * l'initialisation par la liste de ses coordonnées, >>> A = Point(1, 2, 3) * l'accès et la modification des coordonnées du point: >>> A.y 2 * la représentant en chaîne de caractères (`__repr__`): >>> print(A) Point(1.0, 2.0, 3.0) Écrivez une fonction `vector_from_points(A, B)` générant le `Vector` :math:`\vec{AB}` à partir de deux points `A` et `B`: >>> vector_from_points(Point(0, -1, 1), Point(1, 2, 3)) Vector(1.0, 3.0, 2.0) Classe `Plane` -------------- Ajoutez à votre module une classe `Plane`, représentant un plan à *N=3* dimensions, et décrit par les quatre coefficients *a, b, c, d* de son équation cartésienne: .. math:: a\,x + b\,y + c\,z + d = 0 Implémentez les méthodes suivantes: * l'initialisation par 4 coefficients: >>> P = Plane(0, 1, 2, 3) .. attention:: les trois coefficients *a, b, c* ne peuvent pas être nuls simultanément. Si c'est le cas, lever une exception. * la représentant en chaîne de caractères (`__repr__`) >>> str(P) 'Plane(0, 1, 2, 3)' * la méthode `get_point(self)` retournant un point quelconque du plan, p.ex. :math:`(0, 0, -d/c)` si :math:`c \not= 0`. .. attention:: aux cas où un des coefficients *a, b, c* est nul (par construction, ils ne peuvent pas tous l'être simultanément). * la méthode `__contains__` testant si un point fait partie du plan (à une précision arbitraire de `1e-6`). * la méthode `get_normal(self)` retournant le vecteur normal :math:`\vec{n}` au plan, de coordonnées *(a, b, c)* >>> P.get_normal() Vector(0.0, 1.0, 2.0) * la méthode `distance(self, A)` pour calculer la distance *d* au plan d'un point `A`, par la formule: .. math:: d = \frac{\left|\vec{n} \cdot \vec{AM}\right|}{\vec{n}} où *M* est un point quelconque du plan, et :math:`\vec{n}` le vecteur normal. >>> P.distance(Point(0, 0, 0)) # = √3 / 5 1.3416407864998738 Écrivez enfin une fonction `plane_from_points(A, B, C)` générant un plan `Plane` à partir de trois points `A`, `B` et `C`: >>> A = Point(0, 1, 1) >>> B = Point(1, 0, 1) >>> C = Point(1, 1, 0) >>> P = plane_from_points(A, B, C) >>> print(P) Plane(1.0, 1.0, 1.0, -2.0) .. tip:: Calculez le vecteur normal :math:`\vec{AB} \wedge \vec{AC}`, dont les coordonnées *a, b, c* sont les coefficients du plan, puis :math:`d = -(a\,x_A + b\,y_A + c\,z_A)`. .. attention:: La fonction devra lever une exception si les trois points sont colinéaires (et donc si le vecteur normal :math:`\vec{AB} \wedge \vec{AC}` est nul).