Mathématiques avec Python et Ruby/Points en Python

L'objet "Point" est une bonne manière d'aborder la programmation objet. En géométrie repérée, un point est constitué de deux nombres, son abscisse et son ordonnée. 
=Création de l'objet=
Le point de coordonnées "(x,y)" est, en "Python", une classe:
class Point:
 def __init__(self,x,y):
 self.x=x
 self.y=y
Lorsqu'on crée un point, ses coordonnées sont stockées à l'intérieur de l'objet. On note "p.x" et "p.y" les coordonnées de "p".
=Affichage=
La méthode peut ressembler à ceci:
 def affichage(self):
 return '('+str(self.x)+';'+str(self.y)+')'
mais on peut envisager d'y rajouter des instructions avec "TkInter" pour réellement dessiner le point sur la figure. Voir à ce sujet le chapitre sur les fonctions.
=Avec deux points=
Le plus simple quand on a deux points, c'est leur milieu, parce que c'est aussi un point (donc un objet de même nature).
Milieu.
Les coordonnées du milieu d'un segment sont les moyennes de celles des extrémités:
 def milieu(self,p):
 return Point((self.x+p.x)/2,(self.y+p.y)/2)
En se rappelant que l'équivalent en Java de "self" est "this", on remarque une certaine ressemblance avec les codes sources de logiciels de géométrie dynamique:
Tout d'abord, CaRMetal:
 setXY((P1.getX() + P2.getX()) / 2, (P1.getY() + P2.getY()) / 2);
Ensuite, GeoGebra:
 M.setCoords(
 (P.inhomX + Q.inhomX) / 2.0d,
 (P.inhomY + Q.inhomY) / 2.0d,
 1.0);
Remarque: Ces codes sources sont sous licence GPL ce qui autorise à les citer, au nom de la liberté numéro 1 (celle d'étudier le logiciel) de Richard Stallman.
Vecteur.
Le vecteur d'origine "A" et d'extrémité "B", noté formula_1, est un vecteur! On le définira donc au chapitre suivant mais il peut servir ici:
 def vecteur(self,p):
 return Vecteur(p.x-self.x,p.y-self.y)
Distance.
Pour simplifier l'écriture de la distance "AB" on va encore utiliser les vecteurs, la distance "AB" étant égale à formula_2:
 def distance(self,p):
 return self.vecteur(p).norme()
=Application au problème=
Voici l'objet "Point" en entier:
from math import *
class Point:
 def __init__(self,x,y):
 self.x=x
 self.y=y
 def affichage(self):
 return '('+str(self.x)+';'+str(self.y)+')'
 def milieu(self,p):
 return Point((self.x+p.x)/2,(self.y+p.y)/2)
 def vecteur(self,p):
 return Vecteur(p.x-self.x,p.y-self.y)
 def distance(self,p):
 return self.vecteur(p).norme()
Nature de ABC.
Pour savoir si ABC est isocèle, on peut calculer les longueurs de ses trois côtés:
a=Point(-1,3)
b=Point(5,1)
c=Point(1,5)
print(a.distance(b))
print(a.distance(c))
print(b.distance(c))
Visiblement, ABC n'est pas isocèle. Mais 
print(a.distance(b)**2)
print(a.distance(c)**2+b.distance(c)**2)
La réciproque du théorème de Pythagore nous apprend que ABC est rectangle en C, donc d'hypoténuse "AB".
Centre du cercle.
Donc le cercle circonscrit a pour diamètre "[AB]", donc pour centre le milieu de "[AB]":
m=a.milieu(b)
print(m.affichage())
Rayon du cercle.
On peut donc diviser par 2 la distance "AB" mais aussi vérifier que "M" est équidistant de "A", "B" et "C":
print(m.distance(a))
print(m.distance(b))
print(m.distance(c))
Figure.
On pourrait utiliser "TkInter" pour dessiner le tout (y compris le cercle) mais la figure ci-dessous a été faite avec Ruby, ce langage permettant assez facilement de fabriquer un fichier au format svg:

Mathématiques avec Python et Ruby/Points en Ruby

L'objet "Point" est une bonne manière d'aborder la programmation objet. En géométrie repérée, un point est constitué de deux nombres, son abscisse et son ordonnée. 
=Classe=
Pour que "Ruby" possède un objet "Point", il suffit de le définir, sous la forme d'une "classe":
class Point
 def initialize(x,y)
 @x, @y = x, y
 end
end
Dorénavant, chaque fois qu'on crée un point par "Point.new(x,y)", celui-ci possédera les coordonnées "x" et "y" qui sont pour l'instant ses seules propriétés (des variables stockées temporairement dans l'objet).
=Coordonnées=
Cependant pour accéder depuis l'extérieur aux coordonnées du point, il faut les redéfinir comme des méthodes "Ruby" (parce que dans "Ruby", tout est méthode). 
Abscisse.
Il suffit de dire que la méthode "x" renvoit le nombre "x":
 def x
 @x
 end
Ordonnée.
Idem pour "y":
 def y
 @y
 end
Dorénavant, l'abscisse de "P" s'appelle "P.x" et son ordonnée, "P.y".
=Affichage=
Pour afficher un objet, il faut utiliser la conversion "to_s" que "Ruby" propose. Dans le cas présent, puisqu'on a inventé un nouvel objet, on doit redéfinir cette conversion en chaîne de caractères en mettant les coordonnées entre parenthèses, séparées par un point-virgule:
 def to_s
 '('+@x.to_s+';'+@y.to_s+')'
 end
Pour afficher un point "M", on peut faire 
puts(M.to_s)
mais aussi
puts(M)
puisque "Ruby" se charge automatiquement de la conversion "to_s".
=Deux points=
Le plus simple avec deux points, c'est le milieu, parce que c'est un objet de même type (un point):
Milieu.
 def milieu(q)
 Point.new((@x+q.x)/2,(@y+q.y)/2)
 end
La syntaxe est typique de "Ruby": On parle de "milieu avec q" en invoquant
puts(p.milieu(q))
Vecteur.
Un peu hors sujet ici (on en reparlera dans le chapitre qui leur est consacré), le vecteur formula_1 est bel et bien associé à deux points: son origine "A" et son extrémité "B". Et ses coordonnées se calculent à partir de celles de "A" et de "B":
 def vecteur(q)
 Vecteur.new(q.x-@x,q.y-@y)
 end
Ce qui oblige, soit à placer la classe vecteur dans le même fichier, soit à l'importer avec
require 'vector'
si on a enregistré ladite classe dans un fichier "vector.rb".
Là encore, on parle de méthode "vecteur jusqu'à q" pour un point "p".
Distance.
La distance jusqu'à "q" est un nombre, mais associé à deux points:
 def distance(q)
 (self.vecteur(q)).norme
 end
Pour faire le plus simple possible, on a là encore utilisé le fichier des vecteurs sous la forme de sa méthode "norme": La distance AB est la norme du vecteur formula_1, qu'on calcule avec la fonction "hypot" de "Ruby" (voir au chapitre suivant comment on l'utilise). 
Pour calculer la distance entre "p" et "q", on entre
puts(p.distance(q))
ou, au choix,
puts(q.distance(p))
=Application au problème=
Pour récapituler, la classe "Point" en entier est décrite ici:
class Point
 def initialize(x,y)
 @x, @y = x, y
 end
 def x
 @x
 end
 def y
 @y
 end
 def to_s
 '('+@x.to_s+';'+@y.to_s+')'
 end
 def milieu(q)
 Point.new((@x+q.x)/2,(@y+q.y)/2)
 end
 def vecteur(q)
 Vecteur.new(q.x-@x,q.y-@y)
 end
 def distance(q)
 (self.vecteur(q)).norme
 end
end
C'est tout!
On commence par créer trois points, les sommets du triangle:
a=Point.new(-1,3)
b=Point.new(5,1)
c=Point.new(1,5)
Nature de ABC.
Pour voir si ABC est isocèle, on peut afficher les longueurs de ses côtés:
puts(a.distance(b))
puts(a.distance(c))
puts(b.distance(c))
mais on n'apprend pas grand-chose (sinon qu'il n'est pas isocèle). Mais on peut chercher s'il est rectangle avec la réciproque du théorème de Pythagore:
puts(a.distance(b)**2)
puts(a.distance(c)**2+b.distance(c)**2)
C'est clair, le triangle ABC est rectangle en C. 
Centre du cercle.
Il en résulte alors que le cercle circonscrit a pour diamètre "[AB]", donc pour centre le milieu "M" de "[AB]" et pour rayon la moitié de AB:
m=a.milieu(b)
puts(m)
Rayon du cercle.
Le rayon peut se calculer en divisant par 2 la distance AB, ou mieux, en vérifiant que les trois rayons MA, MB et MC ont la même longueur à la précision permise par "Ruby":
puts(m.distance(a))
puts(m.distance(b))
puts(m.distance(c))
Figure.
On peut résumer le tout en modifiant le script ci-dessus pour qu'il crée des éléments "svg", dont le résultat est visible ci-dessous:

Mathématiques avec Python et Ruby/Vecteurs en Ruby