Cadran de hauteur plan à style fixe

Dans un article de la revue Cadran-Info de mai 2021 page 51 (“Cadrans cylindriques de Hartmann”), Henri et Paul Gagnaire décrivent la maquette d’un cadran de hauteur original. Le présent billet en propose une réalisation.

Les courbes horaires sont tracées sur un plan. L’échelle horizontale constitue un calendrier. Une épingle tient lieu de style, ici. Perpendiculaire au plan, le style est placé sur la verticale correspondant au solstice d’été.

Pour lire l’heure, il faut disposer le cadran verticalement, en l’orientant de manière à ce que l’extrémité de l’ombre du style atteigne la ligne de la date du jour.

Sur la photo précédente : réglage sur le 10 novembre, on lit 15h30 (photo prise l’après-midi). Sur ce tracé, une simplification a été adoptée : les lignes verticales de dates sont régulièrement espacées de 10 jours (ce qui rend le mois de février aussi long que les autres…) J’estime que cette simplification induit une erreur qui reste inférieure à la précision du cadran. Elle évite de multiplier les lignes verticales, car le calendrier est replié (janvier à juin vers la droite, puis juillet à décembre vers la gauche).

On peut comparer ce cadran solaire au cadran de berger, dont le style se déplace sur la verticale de la date. Sur le cadran de berger, du fait des fluctuations de la hauteur du Soleil au cours de l’année, les lignes horaires sont très resserrées au solstice d’hiver mais très étendues au solstice d’été. Plusieurs solutions peuvent être imaginées pour résoudre ce problème. On peut trouver dans des collections de musées des cadrans de berger munis de deux styles de longueurs différentes, avec deux ensembles de lignes (été et hiver).

Le cadran plan à style fixe, quant à lui, imagine un “style droit virtuel” d’autant plus long que l’on s’éloigne du solstice d’été.

Le cadran vu de haut

Ainsi, dans la formule calculant la hauteur des lignes, la longueur du style virtuel est l’hypoténuse du triangle ESH. Deux effets s’opposent : l’allongement du style virtuel tend à décaler les courbes vers le bas alors que l’approche du solstice d’hiver tend à avoir l’effet inverse.Le résultat est un ensemble de courbes horaires de hauteurs comparables.


Considérations techniques sur le calcul des courbes horaires :

Le calcul des hauteurs de courbes a été réalisé en rédigeant un code Python. Initialement, je comptais utiliser ce même code pour tracer les courbes (module matplotlib de Python), mais je me suis heurté à une limitation : avec matplotlib, il n’y pas de moyen simple pour fixer exactement les dimensions de l’axe du graphique. Or, ce cadran étant tracé pour une longueur de style donné, une modification de l’échelle à l’impression fausserait la lecture.

J’ai donc utilisé Python uniquement pour générer les résultats des calculs et les stocker dans un fichier csv. Ce dernier est ensuite lu dans un code LaTeX pour tracer les courbes (package pgfplots de LaTeX).

(Au moment où j’écris ces lignes, je cherche encore à trouver une solution qui n’utilise que Python).

Le code Python de calcul des courbes horaires :

#Calculs d'un cadran solaire de hauteur plan, à style fixe

import numpy as np
import pandas as pd

#paramètres de départ :----------------------------------------------
latitude=np.radians(49.5)#REGLAGE LATITUDE
a=3.0#longueur du style 
largeur=18#largeur du plan, pour l'échelle horizontale(

#Modèle déclinaison selon le rang J du jour :
def declinaison(J):
    return np.arcsin(np.sin(np.radians(23.44))*np.sin((J-81)*2*np.pi/365.2422))

#------------------------------------------------------------------------------------

Ah=np.arange(0, 120+7.5, 7.5)#étendue de l'angle horaire, par demi-heure
J=np.arange(1, 365, 0.01)#rang du jour dans l'année
N=np.arange(1, 183, 1)#rang du jour après 21 juin
decl=declinaison(N+171)#déclinaison après le 21 juin
x=-largeur/183*N#distance horizontale au 21 juin
b=np.sqrt(a**2+x**2)#taille du style virtuel, à une date donnée

donneesC=pd.DataFrame({"x":x})#fichier qui recevra les résultats des calculs

#------------------------------------------------------------------------------------------
#Calcul des lignes horaires
for H in Ah:
    h=np.arcsin(np.sin(decl)*np.sin(latitude)+np.cos(decl)*np.cos(latitude)*np.cos(np.radians(H)))
    y=-b*np.tan(h)

    nomHeure='h'+str(round(H, 1))#nom de la colonne dans le fichier
    DF=pd.DataFrame({nomHeure:y})
    donneesC=pd.concat([donneesC, DF], axis=1)#ajout d'une colonne

donneesC.to_csv("donnees.csv")
    

Le code LaTeX de tracé :

\documentclass[border=0.5cm,11pt,convert={ghostscript,outext=.png,density=800x800}]{standalone}%conversion en png avec ghostscript

%COMPILé AVEC XeLaTeX

\usepackage[T1]{fontenc}
\usepackage[dvipsnames,svgnames]{xcolor}
\colorlet{vert}{OliveGreen!70!black}
\colorlet{rouge}{red!80!black}
\colorlet{monorange}{yellow!50!red}
\usepackage{lmodern}
\usepackage{comment}
\mathcode`\.="013B%virgule décimale en mode math
\usepackage{tikz}
\usetikzlibrary{decorations.text}
\usetikzlibrary{calc,scopes}
\usetikzlibrary{arrows.meta}
\usetikzlibrary{arrows,arrows.meta}
\usetikzlibrary{patterns}
\usetikzlibrary{intersections}
\usetikzlibrary {datavisualization.formats.functions}
\tikzset{every picture/.style={line cap=round}}
\usepackage{mhchem}
\usepackage{pgfplots}\pgfplotsset{compat=newest}
\pgfplotsset{/pgf/number format/.cd,1000 sep={~}}
\usepackage{pgfmath}
\usepackage{siunitx}
\usepackage{ifthen}
\mathcode`\.="013B%virgule décimale en mode math

\begin{document}

\begin{tikzpicture}
\def\style{3.0}
\def\latitude{49.5}
\begin{axis}
[thick,
xmin=-18,
xmax=0,
ymax=0,
title=Cadran de hauteur à style fixe (latitude \textcolor{rouge}{\textbf{\pgfmathprintnumber{\latitude}°}} -- style \textcolor{rouge}{\textbf{\pgfmathprintnumber{\style} cm}}),
width=18cm,
scale only axis,
axis equal,
xtick distance =3,
xtick={-19,-16,-13,-10,-7,-4,-1},
xticklabels={X,D,N,O,S,A,J},
minor x tick num=2,
yticklabel=\empty,
ytick=\empty,
grid=both,
]
\addplot [RoyalBlue] table [x=x,y=h0.0,col sep=comma] {donnees.csv};
\addplot [orange] table [x=x,y=h15.0,col sep=comma] {donnees.csv};
\addplot [OliveGreen] table [x=x,y=h30.0,col sep=comma] {donnees.csv};
\addplot [Crimson] table [x=x,y=h45.0,col sep=comma] {donnees.csv};
\addplot [violet] table [x=x,y=h60.0,col sep=comma] {donnees.csv};
\addplot [brown] table [x=x,y=h75.0,col sep=comma] {donnees.csv};
\addplot [purple] table [x=x,y=h90.0,col sep=comma] {donnees.csv};
\addplot [gray] table [x=x,y=h105.0,col sep=comma] {donnees.csv};
\addplot [vert] table [x=x,y=h120.0,col sep=comma] {donnees.csv};
%%%%%%%%%%%%%%%%% Demi-heures :
\addplot [dotted,gray] table [x=x,y=h22.5,col sep=comma] {donnees.csv};
\addplot [dotted,gray] table [x=x,y=h37.5,col sep=comma] {donnees.csv};
\addplot [dotted,gray] table [x=x,y=h52.5,col sep=comma] {donnees.csv};
\addplot [dotted,gray] table [x=x,y=h67.5,col sep=comma] {donnees.csv};
\addplot [dotted,gray] table [x=x,y=h82.5,col sep=comma] {donnees.csv};
\addplot [dotted,gray] table [x=x,y=h97.5,col sep=comma] {donnees.csv};
\addplot [dotted,gray] table [x=x,y=h112.5,col sep=comma] {donnees.csv};
%Position du style:
\draw [rouge] (0,0) circle (5pt)node[below left]{\small style};
%Repères saisons :
\draw (0,-12)node[rotate=90,anchor=south]{\small solstice d'été};
\draw (-18,-12)node[rotate=90,anchor=north]{\small solstice d'hiver};
\draw [gray,dashed,thin](-9.1,-16)--(-9.1,0)node[pos=0.1,rotate=90,fill=white,]{\small équinoxes};
%%%%%%%%%%%%%%%%%%%
%Mois janvier à juin :
\draw (-17,-15.2)node{J};
\draw (-14,-15.2)node{F};
\draw (-11,-15.2)node{M};
\draw (-8,-15.2)node{A};
\draw (-5,-15.2)node{M};
\draw (-2,-15.2)node[xshift=3mm]{Juin};
%Flèche du calendrier
\draw (-3,-15.3)node{$\rightarrow$};
%%%%%%%%%%%%%%%%%%%

%%%%%%%%%%%%%%%%%%%%%%%
%Graduations heures :
\pgfmathsetmacro{\hauteur}{asin(sin(23.4)*sin(49.5)+cos(23.4)*cos(49.5)*cos((6-12)*15))}
\pgfmathsetmacro{\yb}{-\style*tan(\hauteur)}
\draw (-0.5,\yb)node[circle,fill=white,inner sep=0pt,minimum width=5mm]{\pgfmathprintnumber{6}};
\pgfmathsetmacro{\hauteur}{asin(sin(23.4)*sin(49.5)+cos(23.4)*cos(49.5)*cos((7-12)*15))}
\pgfmathsetmacro{\yc}{-\style*tan(\hauteur)}
\draw (-0.5,\yc)node[circle,fill=white,inner sep=0pt,minimum width=5mm]{\pgfmathprintnumber{7}};
\pgfmathsetmacro{\hauteur}{asin(sin(23.4)*sin(49.5)+cos(23.4)*cos(49.5)*cos((8-12)*15))}
\pgfmathsetmacro{\yd}{-\style*tan(\hauteur)}
\draw (-0.5,\yd)node[circle,fill=white,inner sep=0pt,minimum width=5mm]{\pgfmathprintnumber{8}};
\pgfmathsetmacro{\hauteur}{asin(sin(23.4)*sin(49.5)+cos(23.4)*cos(49.5)*cos((9-12)*15))}
\pgfmathsetmacro{\ye}{-\style*tan(\hauteur)}
\draw (-0.5,\ye)node[circle,fill=white,inner sep=0pt,minimum width=5mm]{\pgfmathprintnumber{9}};
\pgfmathsetmacro{\hauteur}{asin(sin(23.4)*sin(49.5)+cos(23.4)*cos(49.5)*cos((10-12)*15))}
\pgfmathsetmacro{\yf}{-\style*tan(\hauteur)}
\draw (-0.5,\yf)node[circle,fill=white,inner sep=0pt,minimum width=5mm]{\pgfmathprintnumber{10}};
\pgfmathsetmacro{\hauteur}{asin(sin(23.4)*sin(49.5)+cos(23.4)*cos(49.5)*cos((11-12)*15))}
\pgfmathsetmacro{\yg}{-\style*tan(\hauteur)}
\draw (-0.5,\yg)node[circle,fill=white,inner sep=0pt,minimum width=5mm]{\pgfmathprintnumber{11}};
\pgfmathsetmacro{\hauteur}{asin(sin(23.4)*sin(49.5)+cos(23.4)*cos(49.5)*cos((12-12)*15))}
\pgfmathsetmacro{\yh}{-\style*tan(\hauteur)}
\draw (-0.5,\yh)node[circle,fill=white,inner sep=0pt,minimum width=5mm]{\pgfmathprintnumber{12}};
%%%%%%%%%%%%%%%%%%Heures après-midi :
\draw (-17.5,-5)node[circle,fill=white,inner sep=0pt,minimum width=5mm]{13};
\draw (-17.5,-3.75)node[circle,fill=white,inner sep=0pt,minimum width=5mm]{14};
\draw (-17.5,-2.0)node[circle,fill=white,inner sep=0pt,minimum width=5mm]{15};
\draw (-17.5,-0.28)node[circle,fill=white,inner sep=0pt,minimum width=5mm]{16};
%%%%%%%%%%%%%%%%%%
\end{axis}
\end{tikzpicture}
\end{document}

Mise à jour : code 100 % Python

Voici le tracé réalisé entièrement avec Python et son module matplotlib. Pour adapter à votre latitude, il suffit de modifier la valeur de la latitude dans le code.

Imprimez l’image (l’imprimante peut mettre à l’échelle). Pour construire le cadran solaire, utilisez un style de la longueur du segment figurant sur le tracé.

Dans cette version, j’ai ajouté les lignes d’égale hauteur du Soleil. En effet, rares sont les cadrans de hauteur qui permettent une lecture de la hauteur (la seule exception que je connaisse est le cadran quart de cercle).

Ces lignes de hauteur sont tracées de 5 et 5 degrés.

Exemples de lecture pour la latitude 49.5° :

  • au solstice d’hiver à 14h30, la hauteur du Soleil est de 10° environ.
  • le 1er mai, à 9h, la hauteur du Soleil est de 40° environ.

Pour supprimer ces lignes, il suffit de supprimer le code correspondant dans le programme.


Réalisation concrète du cadran :

Pour assurer la verticalité du plan et la rigidité du style, ce cadran gagnera a être réalisé en bois ou métal. Voici le fichier .svg du plan du cadran, en vue d’une découpe au laser :

Ce dessin a été réalisé avec Inkscape, en exportant le tracé pdf. Inkscape est un logiciel gratuit et multi-plateforme de dessin vectoriel, qui permet l’export en format dxf, un format utilisable pour les découpeuses laser.

Soyez le premier à commenter

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée.