Le pavage hexagonal, un excellent exercice !

Comment le générer ce pavage de manière optimale ?
Imprimer la pageImprimer la page || VERSION PDF: Enregistrer au format PDF
Paver le plan à l’aide d’hexagones ne semble à priori pas bien difficile. Mais si on désire réduire le temps de compilation, il est bon de se poser quelques questions : comment éviter de construire plusieurs fois certains points ou segments, comment étendre les hexagones,etc ?

Extension du pavage à l’aide de deux translations

Si on juxtapose des hexagones pour former un pavage hexagonal, un grand nombre de points et de segments seront construits plusieurs fois, ce qui aura un effet désastreux sur le temps de compilation. De plus, à l’écran, des segments de mêmes extrémités mais crées à des moments différents peuvent être décalés d’un pixel ou deux à cause d’erreurs d’arrondi. Là, plus grave encore, le résultat peut être inacceptable.

D’où la question simple : comment générer le pavage à partir du motif le plus léger possible en évitant les doublons à la construction ?

Cet article est une suite à un débat ouvert sur la question sur le forum du site MathemaTeX. L’auteur a participé à l’échange et propose d’en détailler certains aspects.

Un motif minimal et deux translations simples

Un motif minimal pourrait être le suivant :

Si le côté de l’hexagone mesure 1, les images de ce motif par les translations de vecteurs\vec{u}=\lambda \vec{a} + \mu \vec{b}\vec{a} et \vec{b} ont pour composantes respectives \left(\begin{array}{c} 3\\0 \end{array}\right) et \left(\begin{array}{c} 0\\ \sqrt{3\,} \end{array}\right) , engendrent le pavage.

Notre motif de base est créé en n’utilisant que des déplacements relatifs et des coordonnées polaires. On remarquera que nulle part il n’est fait usage de calculs trigonométriques. Il est recommandé en fait d’éviter le recours aux macros \pgfmathparse [1], là ou c’est possible.

Le code correspondant est particulièrement compact


\begin{tikzpicture}
 \foreach \i in {0,3,...,6}{
   \foreach \j in {0,...,3}{
       \begin{scope}[xshift=\i cm,yshift={\j*1.73052 cm}]
         \draw[red] (0:0) -- ++ (60:1cm)-- ++ (0:1cm)--++(-60:1cm)--++(0:1cm);
         \draw[blue] (0:0)--  ++ (-60:1cm) ++ (0:1cm) --++(60:1cm);
       \end{scope}
       }
    }
\end{tikzpicture}

Et le pavage associé au code précédent est le suivant

Avec d’autres translations

Une autre manière de procéder est de translater les vecteurs dont les extrémités sont les racines cubiques de l’unité (en rouge ci-dessous) [2] selon les vecteurs combinaisons linéaires de

\overrightarrow{t_1} de composantes \left(\begin{array}{c} 0\\ \sqrt{3\,} \end{array}\right) et de \overrightarrow{t_2} de composantes \left(\begin{array}{c} 3/2\\ \sqrt{3\,}/2 \end{array}\right)


 \begin{tikzpicture}
   \foreach \i in {-1,...,2}{
       \begin{scope}[yshift={\i*1.73052 cm}]
         \foreach \j in {-2,...,3}{
           \begin{scope}[xshift={\j*1.5 cm},yshift={\j*0.86603 cm}]               
              \draw[->,thick] (0:0)--(0:0.95cm);
              \draw[->,thick] (0:0)--(120:0.95cm);
              \draw[->,thick] (0:0)--(240:0.95cm);
            \end{scope}
            }
        \end{scope}
        }
        \draw[->,very thick,red] (0:0)--(0:0.95cm);
        \draw[->,very thick,red] (0:0)--(120:0.95cm);
        \draw[->,very thick,red] (0:0)--(240:0.95cm);
        \draw[->,very thick,blue] (0,0)--(0,1.73)node[right,midway]{$\vec{t_1}$};
        \draw[->,very thick,blue] (0,0)--(1.5,0.866)node[above,midway]{$\vec{t_2}$};
 \end{tikzpicture}

Petit inconvénient, le pavage s’étend selon la direction de \overrightarrow{t_2}. Il suffit dans ce cas de « clipper » [3] la figure pour qu’elle apparaisse dans un rectangle [4].

Remarquons que les images d’un point (par exemple l’origine A'(0,0) par les combinaisons linéaires des translations \overrightarrow{t_1} et \overrightarrow{t_2}) ne couvrent pas tout le réseau hexagonal. Il faut encore adjoindre par exemple A(1,0) et ses images. Les sommets du pavage sont en fait la réunion de deux réseaux rectangulaires (en rouge et bleu sur la figure ; on consultera cette page). Deux petites macros simplistes et naïves permettant de placer ces points se trouvent dans le fichier TeX joint à cet article.

Repérer des points sur de tels réseaux peut-être très utile pour proposer des exercices, même élémentaires, sur les vecteurs dès la 4ème année.

Génération radiale du pavage

La génération du pavage peut aussi se faire radialement, à la manière des palettes de couleurs sur certains logiciels [5].

L’idée est ici de construire un motif qui représente un sixième de la figure. Les rotations d’un sixième de tour autour de l’origine achèvent de générer le pavage radial. On s’en doute : une certaine attention doit être portée à la création des boucles \foreach... On remarquera qu’ici aussi , chaque segment n’est tracé qu’une et une seule fois.

Et voici la figure complète...

... produite à l’aide du code suivant


\begin{tikzpicture}[scale=0.4]
 \def\n{6}% \n is the number of layers around the initial hexagon. Warning! Bug if n<2
 \def\a{2.598076} % 1.5*sqrt(3)
 \def\b{1.732051} % sqrt(3)
 \def\c{0.866025} % sqrt(3)/2
 \foreach \r in {0,...,5}{
 \begin{scope}[rotate={\r*60}]
     \draw[blue,thick]
        (30:1cm)--++(-90:1cm)
        \foreach \i in {1,...,\n}{
           -- ++ (-30:1cm)
           -- ++ (+30:1cm)
           }
        \foreach \i in {1,...,\n}{
            --++(90:1cm)
            --++(150:1cm)
            }
       ; % end of 'draw'
       \pgfmathparse{\n-1} \let\nn\pgfmathresult
       \pgfmathparse{\n-2} \let\nnn\pgfmathresult
       \foreach \i in {\nnn,...,0}{
         \foreach \j in {0,...,\i}{
            \pgfmathparse{\a+\b*\j+\c*(\nnn-\i)} \let\x\pgfmathresult
            \pgfmathparse{1.5*(\nnn-\i)+0.5} \let\y\pgfmathresult
            \begin{scope}[xshift={\x cm},yshift={\y cm}]
               \draw[blue,thick]  (0,0)--(-90:1cm);
               \draw[blue,thick]  (0,0)--(30:1cm);
               \draw[blue,thick]  (0,0)--(150:1cm);
             \end{scope}
             }
    }
 \end{scope}
 }
\end{tikzpicture}

Ce code n’est sans doute pas optimal, chaque segment n’est construit qu’une fois mais il est peut-être possible de limiter le recours aux \pgfmathparse .

La construction de la figure précédente a, entre autres, été motivée par l’exercice suivant : en générant radialement un hexagone en couches successives, comment varie le nombre d’hexagones du pavage en fonction du nombre de couches ?

Ce n’est pas fini !

Les quelques exemples qui précèdent ne sauraient bien sûr épuiser le sujet des pavages hexagonaux. Ces exemples, qui n’ont nécessité le tracé d’aucun hexagone, ne font que tracer le pavage sans même essayer de colorier ses pavés.

L’informaticien, qui cherche à optimiser son code [6], aura remarqué que les noeuds des réseaux hexagonaux de nos exemples sont recalculés plusieurs fois [7]. Pour éviter cet écueil une meilleure approche serait de créer les sommets une et une seule fois (en utilisant le double réseau rectangulaire), de les nommer et de tracer les segments ensuite.

Bon travail !

[1] cette macro pgf effectue les calculs en virgule flottante et peut se révéler gourmande en temps

[2] pour que la figure soit claire, les vecteurs ont été légèrement raccourcis

[3] macro \clip(x,y) rectangle (z,t) ; à placer en première ligne de l’environnement tikzpicture

[4] on peut aussi faire pivoter la figure de -30° (option [rotate=-30] de l’environnement tikzpicture

[5] ici, Cabri II Plus

[6] tout en essayant de le rendre lisible...

[7] une ou trois fois dans la construction avec les translations \overrightarrow{t_1} et \overrightarrow{t_2}





Mis en ligne le 4 février 2011 par Vermeiren Hugues