L'usage de ces deux fonctions est typique de pratiquement toutes les maths: On commence (avec "frac2cont") par transporter tout le problème dans un espace (celui des fractions continues) où il est plus facile à résoudre; on en profite pour le résoudre, puis on transporte sa solution (par "cont2frac") dans l'espace de départ où on peut exploiter sa solution. Ce procédé est si répandu qu'il porte un nom: La conjugaison (exemples connus: Changement de bases en calcul matriciel, transformées de Fourier et de Laplace etc.). Le mot "conjugaison" semble dù à Galois.
Fils d'une fraction.
function fils(f){
 var cont=frac2cont(f);
 cont[cont.length-1]++;
 return cont2frac(cont);
Fille d'une fraction.
function fille(f){
 var cont=frac2cont(f);
 cont[cont.length-1]--;
 cont[cont.length]=2;
 return cont2frac(cont);
Les fonctions précédentes sont à mettre dans l'entête ("head") du document, celles du dessin de l'arbre pouvant être placées dans le corps ("body"), entre les deux balises qui ouvrent et ferment le "canvas" (et même en ajoutant des balises "script" puisque c'est encore du JavaScript):
Dessin de l'arbre.
Pour simplifier les fonctions JavaScript ci-dessus, on se limite à la partie de l'arbre de Stern-Brocot qui se trouve entre 0 et 1 (ça évite de s'encombrer de parties entières). L'arbre sera donc tracé à partir de la fraction 1/2. Mais la fonction le définissant doit être plus générale, et admettre en entrée une fraction, pour permettre une définition récursive.
Définition récursive.
Pour dessiner l'arbre d'une fraction,
Ainsi, la définition de l'arbre fait appel à la notion d'arbre, pourtant en cours de définition: Récursivité!. Cette définition récursive est courte et ne nécessite pas de savoir où se trouvent le fils et la fille (l'un d'eux à à gauche, mais on n'a pas besoin de savoir lequel).
function arbre(f){
 if (f[1]<400){
 pinceau.moveTo(400*f[0]/f[1],400/f[1]);
 var f1=fils(f);
 pinceau.lineTo(400*f1[0]/f1[1],400/f1[1]);
 var f2=fille(f);
 pinceau.moveTo(400*f[0]/f[1],400/f[1]);
 pinceau.lineTo(400*f2[0]/f2[1],400/f2[1]);
 arbre(f1);
 arbre(f2);
Après ça, il suffit d'appeler la fonction "arbre([1,2])" puis un "stroke()" fait le dessin:
Arbre de Stern-Brocot.
<html>
<head>
<script>
function cont2frac(c){
 //suite des numérateurs et des dénominateurs
 var num=[0,1];
 var den=[1,0];
 for(n in c){
 num=[c[n]*num[0]+num[1],num[0]];
 den=[c[n]*den[0]+den[1],den[0]];
 return [num[0],den[0]];
function frac2cont(f){
 var cont=[Math.floor(f[1]/f[0])];
 for(var n=0;f[1]>1;n++){
 f=[f[1],f[0]];
 f[0]-=cont[n]*f[1];
 cont[n+1]=Math.floor(f[1]/f[0]);
 cont.pop();
 return cont;
function fils(f){
 var cont=frac2cont(f);
 cont[cont.length-1]++;
 return cont2frac(cont);
function fille(f){
 var cont=frac2cont(f);
 cont[cont.length-1]--;
 cont[cont.length]=2;
 return cont2frac(cont);
</script>
</head>
<style type="text/css">
</style>
<body>
<canvas id="cadre" width="400" height="200">
<script>
var chevalet=document.getElementById('cadre');
var pinceau=chevalet.getContext('2d');
pinceau.strokeStyle="Green";
pinceau.beginPath();
function arbre(f){
 if (f[1]<400){
 pinceau.moveTo(400*f[0]/f[1],400/f[1]);
 var f1=fils(f);
 pinceau.lineTo(400*f1[0]/f1[1],400/f1[1]);
 var f2=fille(f);
 pinceau.moveTo(400*f[0]/f[1],400/f[1]);
 pinceau.lineTo(400*f2[0]/f2[1],400/f2[1]);
 arbre(f1);
 arbre(f2);
arbre([1,2]);
pinceau.stroke();
</script>
</canvas>
<br/>
</body>
</html>
L'arbre se calcule presque instantanément mais il est long à afficher. Par contre, en s'arrêtant à l'ordre 40 (au lieu de 400), on a déjà quelque chose qui ressemble à un arbre (sauf qu'on voit moins bien l'alignement de la canopée):
Une variante intéressante consiste à diviser l'ordonnée par le dénominateur ("400/f[1]/f[1]" au lieu de "400/f[1]"):
En agrandissant (multiplier les abscisses par 800 au lieu de 400), on aperçoit un détail qui aura de l'importance dans le prochain chapitre:

Programmation objet et géométrie/Les cercles de canvas

En réalité, "canvas" n'a pas de cercles! Cependant il a des arcs de cercle, et pour tracer un cercle, il suffit de tracer un arc allant de 0 radians à 2π radians. La méthode "arc" de l'objet "canvas" accepte 
6 arguments
Les arcs de cercle sont utiles pour faire des diagrammes circulaires ou semi-circulaires en statistiques, mais aussi pour la géométrie hyperbolique. Mais dans cet article on va plutôt réinvestir ce qui a été fait avec l'arbre de Stern-Brocot dans le chapitre précédent. En effet, la version "tassée" de l'arbre (avec division par le double du carré du dénominateur) a une propriété unique: Les cercles centrés sur les fractions et tangents à l'axe des abscisses, sont également tangents entre eux: L'étude de cas portera donc sur les cercles de Ford, une des plus simples parmi les fractales basées sur des cercles (en réalité ce sont des horocycles mais on ne va pas chipoter).
=Cercles de Ford=
Fractions.
Les fonctions sur les fractions (fille et fils) sont les mêmes que dans le chapitre précédent. Et la méthode générale aussi: On va juste dessiner récursivement des cercles au lieu de segments.
Cercles et disques.
Le dessin d'un cercle devient effectif avec "stroke()" (et il peut être intéressant de le précéder d'un "moveTo()" pour éviter les segments parasites). Mais pour mieux voir les cercles, on va utiliser la méthode "fill()" du "canvas", qui rajoute les disques (donc remplit les cercles).
Couleurs.
On remplit les disques de couleur orange et on trace les cercles en rouge foncé avec
pinceau.strokeStyle="rgb(200,0,0)";
pinceau.fillStyle="Orange";
Cercles.
Pour mieux voir le cercle (le bord), il vaut mieux le placer par-dessus le disque (l'intérieur), ce qu'on fait en traçant le cercle après le disque:
function cercles(f){
 if (f[1]<20){
 pinceau.moveTo(800*f[0]/f[1],0);
 pinceau.arc(800*f[0]/f[1],400/f[1]/f[1],400/f[1]/f[1],-Math.PI/2,3/2*Math.PI,true);
 pinceau.stroke();
 cercles(fils(f));
 cercles(fille(f));
 pinceau.fill();
On remarque que chaque cercle est tracé de -π/2 à 3π/2 (au lieu des classiques 0 et 2π); c'est parce que le point de départ du tracé de l'arc de cercle est plus facile à calculer ainsi.
Comme précédemment, il suffit d'appeler la fonction "cercles([1,2])" suivie d'un "stroke()" pour voir apparaître les cercles de Ford:
Tracé.
<html>
<head>
<script>
function cont2frac(c){
 //suite des numérateurs et des dénominateurs
 var num=[0,1];
 var den=[1,0];
 for(n in c){
 num=[c[n]*num[0]+num[1],num[0]];
 den=[c[n]*den[0]+den[1],den[0]];
 return [num[0],den[0]];
function frac2cont(f){
 var cont=[Math.floor(f[1]/f[0])];
 for(var n=0;f[1]>1;n++){
 f=[f[1],f[0]];
 f[0]-=cont[n]*f[1];
 cont[n+1]=Math.floor(f[1]/f[0]);
 cont.pop();
 return cont;
function fils(f){
 var cont=frac2cont(f);
 cont[cont.length-1]++;
 return cont2frac(cont);
function fille(f){
 var cont=frac2cont(f);
 cont[cont.length-1]--;
 cont[cont.length]=2;
 return cont2frac(cont);
</script>
</head>
<style type="text/css">
</style>
<body>
<canvas id="cadre" width="400" height="200">
<script>
var chevalet=document.getElementById('cadre');
var pinceau=chevalet.getContext('2d');
pinceau.strokeStyle="rgb(200,0,0)";
pinceau.fillStyle="Orange";
pinceau.beginPath();
function cercles(f){
 if (f[1]<20){
 pinceau.moveTo(800*f[0]/f[1],0);
 pinceau.arc(800*f[0]/f[1],400/f[1]/f[1],400/f[1]/f[1],-Math.PI/2,3/2*Math.PI,true);
 pinceau.stroke();
 cercles(fils(f));
 cercles(fille(f));
 pinceau.fill();
cercles([1,2]);
pinceau.stroke();
</script>
</canvas>
<br/>
</body>
</html>
=Arcs de cercle=
Pavages du plan hyperbolique.
Les droites et segments hyperboliques sont représentés dans le disque de Poincaré par des arcs de cercle. La balise "canvas" est donc particulièrement adaptée à leur tracé. Par exemple des pavages hyperboliques...
Spirale de Fibonacci.
Avec des arcs de cercle, on peut faire des dessins assez réguliers comme des rosaces ou la "spirale de Fibonacci". Celle-ci fera son apparition dans le prochain chapitre.

Programmation objet et géométrie/Les rectangles de canvas