J’ai pensé qu’il pourrait être intéressant pour certain de savoir comment j’ai tracé les cadrans ci-dessus.
Comme vous le savez certainement, mon langage préféré pour faire ce genre de bricolage est Python. Je suis parti d’un script assez général qui dessine les cadrans analemmatiques sur toutes les orientations de plan à toutes les latitudes et suivant toutes les orientations du porte-ombre.
La difficulté n’est en soi pas si grande si on connaît bien le principe du cadran analemmatique, expliqué par exemple par R. Sagot
dans cet article très pédagogique, et si on utilise les changements de repère évoqués
sur ce fil.
Il « suffit » de définir le cadran armillaire dans le repère équatorial (c’est là où c’est le plus simple), de le ramener dans le repère du cadran et enfin de le projeter sur le cadran suivant la direction que devra prendre le porte-ombre.
Pour dessiner le cadran, je suis passé par un fichier dxf très simplifié dont j’ai rassemblé les routines pour le renseigner dans un script à part (fdxf.py). L’intérêt est que ce script peut ainsi être réutilisé pour d’autres applications.
L’avantage du fichier dxf est qu’il assez standard et il peut être relu avec différents logiciels libres dont LibreCAD ou LibreOffice. C’est ce dernier que j’ai utilisé pour modifier les caractéristiques des traits et rajouter les heures et les mois.
Voici donc les deux scripts qui sont assez court pour retrouverez facilement les principes énoncés plus haut :
Code : Tout sélectionner
def o_dxf(nfic): # Ouvrir le fichier dxf nfic
fic = open(nfic, 'w')
fic.write (' 0\nSECTION\n 2\nENTITIES\n')
return fic # Retourne son identifiant fic
def line(fic, pt1, pt2): # Tracer une ligne
fic.write(' 0\nLINE\n')
fic.write(' 10\n%1.3f\n 20\n%1.3f\n 30\n0.0\n' % pt1)
fic.write(' 11\n%1.3f\n 21\n%1.3f\n 31\n0.0\n' % pt2)
def polyline(fic, pts): # Tracer une polyligne
fic.write(' 0\nPOLYLINE\n 70\n8\n')
for pt in pts:
fic.write(' 0\nVERTEX\n 10\n%1.3f\n 20\n%1.3f\n 30\n0.0\n' % pt)
fic.write(' 0\nSEQEND\n')
def circle(fic, ct, ry): # Tracer un cercle
fic.write(' 0\nCIRCLE\n')
fic.write(' 10\n%1.3f\n 20\n%1.3f\n 30\n0.0\n' % ct)
fic.write(' 40\n%1.3f\n' % ry)
def c_dxf(fic): # Clore le fichier d'identifiant fic
fic.write(' 0\nENDSEC\n 0\nEOF\n')
fic.close()
Code : Tout sélectionner
from math import *
import fdxf
def Rot(x, y, r):
r *= pi/180
return cos(r)*x + sin(r)*y, -sin(r)*x + cos(r)*y
def EtoC(x, y, z): # Changement de coordonnées équatoriales --> cadran
z, x = Rot(z, x, 90 - phi) # ... dans le repère local
x, y = Rot(x, y, -D)
z, x = Rot(z, x, Z) # ... dans le repère cadran
return x, y, z
def Proj(x, y, z): # Projection sur le cadran avec mise à la dimension R
return R*(y - z*yp/zp), R*(z*xp/zp - x)
# Orientation du plan
phi = 49 # Latitude en °, négative dans l'hémisphère sud
D = 71 # Déclinaison en °, négative à l'est
Z = 90 # Inclinaison en ° ou distance zénithale
# Géométrie du tracé
R = 20.0 # Rayon du cadran en mm
prp = 50 # Rapport des longueurs de l'échelle des dates et des tirets
nsg = 3 # Nombre de segment par heure
rp = R/150 # Rayon des points
hd = 10 # Heure du premier point
hf = 20 # Heure du dernier point
# Constantes astronomiques pour le calcul de l'échelle des dates
k = .0172024
jm = 308.7
jl = 21.44
e = .0167
ob = .4091
# Direction de la projection dans le repère cadran
xp, yp, zp = 0, 0, 1 # projection orthogonale
# xp, yp, zp = EtoC(0, 1, 0) # direction de l'est
dxf = fdxf.o_dxf('cadran.dxf')
# Ligne horaire
pths = []
for hv in range(hd*nsg, hf*nsg + 1):
x, y = Rot(1, 0, 15.0*hv/nsg) # Direction du point horaire hv dans le repère polaire
pths.append(Proj(*EtoC(x, y, 0)))
fdxf.polyline(dxf, pths)
# Points des heures et des demi-heures
for hv in range(2*hd, 2*hf + 1):
x, y = Rot(1, 0, 15.0*hv/2) # Direction du point horaire hv dans le repère polaire
x, y = Proj(*EtoC(x, y, 0))
if hv == 2*hd: fdxf.circle(dxf, (x, y), 3*rp)
ct = 1
if hv % 2 == 0: ct = 2
fdxf.circle(dxf, (x, y), ct*rp)
# Ligne des dates
x1, y1 = Proj(*EtoC(0, 0, tan(-ob)))
x2, y2 = Proj(*EtoC(0, 0, tan(ob)))
dx, dy = (y2 - y1)/prp, (x1 - x2)/prp
fdxf.line(dxf, (x1, y1), (x2, y2))
# Tirets des dates
for mo in range(3, 15):
for jo in [1, 11, 21]:
# Nombre de jours écoulés depuis le 1 Mars O h TU
j = int(30.61*(mo + 1)) + jo - 122.5
# Anomalie et longitude moyenne
m = k*(j - jm)
l = k*(j - jl)
# Longitude vrai
s = l + 2*e*sin(m) + 1.25*e*e*sin(2*m)
z = sin(ob)*sin(s)
x, y = Proj(*EtoC(0, 0, z/sqrt(1 - z*z)))
ct = 1
if cos(s) < 0: ct = -1
if jo == 1:
if mo == 3:
fdxf.line(dxf, (x, y), (x + 3*ct*dx, y + 3*ct*dy))
ct *= 2
fdxf.line(dxf, (x, y), (x + ct*dx, y + ct*dy))
fdxf.c_dxf(dxf)
Et le résultat brut que donne le fichier dxf dans LibreOffice Draw :