Browse Source

initialisation

Jackbot 3 years ago
commit
7ce018b411
6 changed files with 1280 additions and 0 deletions
  1. 690 0
      engrenage.scad
  2. 272 0
      math.scad
  3. 105 0
      meca.scad
  4. 38 0
      pavage.scad
  5. 54 0
      symbole.scad
  6. 121 0
      vis.scad

+ 690 - 0
engrenage.scad

@@ -0,0 +1,690 @@
+include <math.scad>
+
+/*Certaines fonctions utilisées dans ce fichier
+sont définies dans le fichier math.scad.
+Notamment la développante de cercle et la fonction permettant
+de calculer son point d'intersection avec un cercle.
+Pour des détails et explications il faut donc regarder
+dans le fichier math.scad*/
+
+/**************ENGRENAGE DROIT**************
+**************DÉFINITIONS**************
+
+le cercle de pied, qui est le cercle passant par la base des dents ;
+le cercle de tête, qui passe par le sommet des dents ;
+le cercle de base, qui est celui qui sert à générer le profil des dents (les dents sont des développantes de ce cercle) ;
+
+le cercle primitif : les cercles primitifs des roues dentées d'un engrenage ont la même vitesse tangentielle ; ils passent à peu près au milieu des dents.
+
+**************NOTATIONS**************
+
+diamètre primitif => d
+diamètre de pied => df
+diamètre de tête => da
+diamètre de base => db
+
+angle de pression => alpha
+
+module => m
+
+pas (distance entre 2 dents sur le cercle primitif) => p
+
+saillie => ha
+creux => hf
+
+hauteur de dent => h
+nombre de dents => z
+
+largeur de la dent sur le cercle primitif => l
+angle d'une dent sur le cercle primitif => la
+
+**************RELATIONS**************
+
+d = m*z
+p = m*pi
+ha = m
+
+si m<=1.25 hf = 1.40*m
+sinon hf = 1.25*m
+
+si m<=1.25 h = 2.40*m
+sinon h = 2.25*m
+
+h = ha + hf <=> ha = h - hf <=> ha = 2.25m - 1.25m = m
+ha = m
+
+da = d + 2*ha = d + 2*m
+df = d - 2*hf = d -2.5*m
+db = d*cos(alpha)
+
+l = pi*m/2 = pi/2 * d/z = (pi * d)/(2 * z) = pi*r/z = p/2
+
+deport de denture
+calcul de la largeur d'une dent avec déport :
+http://www.sidermeca.com/ficheconseil.php?fiche=1
+
+/*************ATTENTION*************
+la différence entre le nombre de dents de 2 roues
+est limité dans certains cas
+
+si Za=13, Zbmax=16
+si Za=14, Zbmax=26
+si Za=15, Zbmax=45
+si Za=16, Zbmax=101
+si Za=17, Zbmax=sans limite
+
+de préférence choisir des nombres premiers entres eux
+*/
+
+$fn = 200;
+
+/*FONCTION EXPERIMENTALE*/
+function recherche_limite(limite = 6, etape = 0, x = 0, y = 0, angle = 0) =
+limite == etape ? atan(x) :
+etape%2 == 0 ? recherche_limite(limite = limite, etape = etape + 1, x = y + rad(angle), y = y, angle = angle) :
+recherche_limite(limite = limite, etape = etape + 1, x = x, y = rad(atan(x)), angle = angle);
+
+
+function creux(m = 1) = m <= 1.25 ? 1.4*m : 1.25*m;
+
+module evider(diam_int = 15, diam_ext = 50, larg = 8, nbr = 6)
+{
+    facteur = 1.7;
+    offset(r = larg/facteur)
+    {
+        difference()
+        {
+            circle(d = diam_ext -0.1);
+            
+            union()
+            {
+                for(i = [0:nbr - 1])
+                {
+                    rotate([0, 0, i*360/nbr])
+                    {square([diam_ext - larg/2, facteur*larg], center = true);}
+                }
+                
+                difference()
+                {
+                    circle(d = diam_ext);
+                    circle(d = diam_ext - 2*larg);
+                }
+            }
+        }
+    }
+}
+
+module dent_cremaillere_2D(m = 1, alpha = 20)
+{
+    //hauteurs
+    hf = creux(m);
+    ha = m;
+    h = hf + ha;
+    
+    //pas
+    p = m*pi;
+    
+    //vecteurs
+    /*calcul des points de la dents
+    
+    1) Premier point [0, 0]
+    
+    En partant de l'origine, on monte jusqu'à y = h suivant un angle alpha. On notera l la longueur de la dent.
+    On peut donc écrire :
+    l*sin(alpha) = decalage_x
+    l*cos(alpha) = h
+    en faisant la première ligne divisé par la seconde on obtient :
+    l*sin(alpha) / l*cos(alpha) = decalage_x / h
+    Or l se simplifie et sin/cos = tan, on obtient donc :
+    tan(alpha) = decalage_x / h
+    et donc decalage_x = h*tan(alpha)
+    
+    2) Deuxième point : [h*tan(alpha), h]
+    
+    Pour le troisième point il faut connaitre la largeur de la dent. Pour y = hf, la largeur de la dent vaut p/2, la largeur de la base est donc :
+    largeur_base = hf*tan(alpha) + p/2 + hf*tan(alpha)
+    <=> largeur_base = 2*hf*tan(alpha) + p/2
+    
+    3) Troisième point : [largeur_base - h*tan(alpha), h]
+    
+    Le quatrième point lui est simplement la largeur de la dent avec y = 0
+    
+    4) Quatrième point : [largeur_base, 0]
+    
+    */
+
+    largeur_base = 2*hf*tan(alpha) + p/2;
+    polygon([ [0, 0], [h*tan(alpha), h], [largeur_base - h*tan(alpha), h], [largeur_base, 0] ]);
+}
+
+module cremaillere_2D(z = 10, m = 1, alpha = 20, largeur = 10)
+{
+    //hauteurs
+	hf = creux(m);
+    
+    //pas
+    p = m*pi;
+    
+    union()
+    {
+        //corps de la crémaillère
+        translate([0, -largeur, 0])
+        {square([p* (z - 1) + p/2 + 2*hf*tan(alpha), largeur]);}
+        
+        //dents de la crémaillère
+        for(i=[0:z-1])
+		{
+            translate([p*i, 0, 0])
+            {dent_cremaillere_2D(m, alpha);}
+        }
+    }
+}
+
+module cremaillere_3D(z = 10, m = 1, alpha = 20, largeur = 10, epaisseur = 3)
+{
+    linear_extrude(epaisseur)
+    {cremaillere_2D(z, m, alpha, largeur);}
+}
+
+module roue_dentee_2D(z = 40, m = 1, alpha = 20, deport = 0, evider = false)
+{    
+	//hauteurs
+	hf = creux(m) - deport;
+    ha = m + deport;
+    
+    //pas
+    p = m*pi;
+    
+    //calcul des diamètres
+    d = m * z;
+    db = d * cos(alpha);
+    df = d - 2*hf;
+    da = d + 2*ha;
+    
+    //calcul de l'angle entre 2 dents
+    angle_dent = 360 / z;
+    
+    //largeur de la dent sur le cercle primitif
+    //l = pi*d/(2*z) + 2*deport*sin(alpha);
+    l = p/2 + 2*deport*sin(alpha);
+    
+    //angle de la dent sur le cercle primitif
+    la = degre(2*l/d);
+    
+    //paramètre d'intersection de la developpante avec le cercle primitif
+    //Id = intersect(db/2, d/2); équivalent à :
+    Id = intersect(db, d);
+    Idx = developpante_x(db/2,Id);
+    Idy = developpante_y(db/2,Id);
+    
+    //angle entre la base de la dent et l'intersection avec le cercle primitif
+    angle = atan2(Idy, Idx);
+    //angle de la dent à sa base
+    angle_base = la + 2*angle;
+    
+    //paramètre d'intersection de la developpante avec le cercle de tête
+    //Ida = intersect(db/2, da/2); équivalent à :
+    Ida = intersect(db, da);
+
+    //GENERATION DE LA DENT
+    
+    /*Lors d'un déport de denture trop prononcé les développantes de cercles se croisent donnant lieu à 
+    un "petit triangle" sur la pointe de la dent. Pour éviter ça il faut déterminer l'angle à ne pas dépasser.
+    
+    La développante de cercle ne devrait jamais croiser l'axe de symétrie de la dent.
+    On en déduit donc que la droite passant par l'origine O et faisant un angle de "angle_base/2" avec l'axe x est la limite.
+    On note I le point d'intersection de cette droite avec la développante de cercle et T un point du cercle de base (angle positif) tel que
+    IT soit une tangente.
+    
+    CARACTÉRISTIQUES CONNUES DE LA FIGURE :
+    0) L'angle xOI est angle_base/2
+    1) L'angle IOT sera appelé alpha
+    2) L'angle xOT est le paramètre de la développante de cercle, on le notera a.
+    3) De part sa construction le triangle OIT est rectangle en T.
+    4) OT est un rayon du cercle de base, on notera sa longueur r
+    5) La longueur IT est proportionnelle à r et à l'angle xOT. Avec a en radiant on obtient : IT = ra
+    6) D'après le théorème de pythagore OI² = IT² + TO²
+    7) Dans un triangle rectangle : hypothénuse * cos(alpha) = coté adjacent
+    
+    DÉDUCTIONS :
+    OI² = IT² + TO²
+    OI² = r²a² + r² = r² * (1 + a²)
+    OI = sqrt(r² * (1 + a²) )
+    OI = r * sqrt(1 + a²)
+    Or OI est l'hypoténuse on peut dont écrire :
+    OI * cos(alpha) = r
+    r * sqrt(1 + a²) * cos(alpha) = r
+    sqrt(1 + a²) * cos(alpha) = 1
+    cos(alpha) = 1 / sqrt(1 + a²)
+    alpha = acos( 1 / sqrt(1 + a²) )
+    
+    Dans le cas où la developpante de cercle est tracé jusqu'au point I alors on a :
+    a = angle_base/2 + alpha
+    Le paramètre a ne doit donc pas dépasser cette valeur.
+    
+    */
+    
+    A = [ for(i=[0: ceil(Ida)])
+           if( i < angle_base/2 + acos( sqrt( 1/(1 + rad(i) * rad(i)))) )
+           [developpante_x(db/2,i), developpante_y(db/2,i)] ];
+    
+    Matrice_de_rotation = [ [cos(angle_base), -sin(angle_base)], [sin(angle_base), cos(angle_base)] ];
+    
+    //Pour continuer le polygone il faut parcourir les valeurs dans l'autre sens
+    B = [ for(i=[floor(-Ida):0])
+          if( i > -angle_base/2 - acos( sqrt( 1/(1 + rad(i) * rad(i)))) ) 
+          Matrice_de_rotation*[developpante_x(db/2,i), developpante_y(db/2,i)] ];
+                        
+    C = concat(A, B);
+
+    difference()
+    {
+        union()
+        {
+            //pied de la dent
+            circle(d=df);
+            
+            for(j = [0:1:z-1])
+            {
+                rotate([0, 0, j*angle_dent])
+                {polygon(C);}
+            }
+        }
+        
+        if(evider)
+        {evider(diam_int = 3*da/10, diam_ext = 9*da/10, larg = 1.2*da/10, nbr = 6);}
+
+    }
+}
+
+module roue_dentee_3D(z = 20, m = 5, alpha = 20, epaisseur = 2, deport = 0, evider = false)
+{
+    linear_extrude(epaisseur)
+    {roue_dentee_2D(z,m,alpha, deport, evider);}
+}
+
+module roue_dentee_3D_globoide(z = 20, m = 5, alpha = 20, epaisseur = 2, deport = 0, evider = false)
+{
+	/*pour créer une roue globoïde on coupe les dents de la roue avec un tore
+	le rayon R du cercle qui engendre le tore par révolution peut être calculer en considérant
+	que les extrémités d'une dent forment une corde de ce cercle.
+	https://fr.wikipedia.org/wiki/Segment_circulaire
+	
+	l'angle theta peut être trouvé en traçant la bissectrice de cet angle,
+	on obtient un triangle rectangle avec des cotés ayant pour longueur h et c/2.
+	
+			B angle beta
+			|\
+		   h| \
+	     __|__\A
+			c/2
+	
+	l'angle beta peut se calculer en utilisant la tangente :
+	
+	tan(beta) = (c/2)/h
+	beta = atan(c/2h)
+	
+	Or le triangle ABO, avec O le centre du cercle est isocèle, et l'angle en 0 est theta/2
+	On en déduit que 2*beta + theta/2 = 180 et donc que :
+	theta/2 = 180 - 2*beta
+	
+	En remplaçant dans la relation c = 2*R*sin(theta/2) on obtient :
+	c = 2*R*sin(180 - 2*beta)
+	or sin(180 - x) = sin(x)
+	c = 2*R*sin(2*beta)
+	
+	on peut maintenant déduire R :
+	
+	R = c / 2*sin(2*beta) = c / 2*sin( 2*atan(c/2h) )
+	
+	Dans le cas de notre roue dentée :
+	c = epaisseur
+	h = (da - d)/2
+	
+	On en conclue que :
+	
+	R = epaisseur / 2*sin(2*atan(epaisseur/(da-d))
+	
+	On peut également utiliser la fonction atan2
+	R = epaisseur / 2*sin(2*atan2(epaisseur, (da-d))
+	*/
+	
+	d = m*z;
+    da = d + 2*m;
+	
+	difference()
+	{
+		linear_extrude(epaisseur)
+		{roue_dentee_2D(z,m,alpha, deport, evider);}
+		
+		rayon = epaisseur / (2*sin(2*atan2(epaisseur, (da-d))));
+        
+        translate([0, 0, epaisseur/2])
+        {
+            rotate_extrude()
+            {
+                translate([d/2 + rayon, 0, 0])
+                {circle(rayon);}
+            }
+        }
+	}
+}
+
+/**************ENGRENAGE HELICOÏDAL**************/
+/*Dans un engrenage hélicoïdal la denture est "penchée", on distingue donc 2 profiles
+
+-Le profil réel, qui correspond à une coupe droite de la dent, une coupe par un plan perpendiculaire aux arêtes, module réel noté mr (noté parfois mn)
+
+-Le profil apparent, qui correspond à une coupe selon un plan perpendiculaire à l'axe du cylindre, module apparent : ma (noté parfois mt)
+
+le module réel "mr" et le module apparent "ma" sont lié par :
+mr = ma*cos(beta)
+
+beta étant l'angle que fait la dent avec l'axe de rotation
+
+**************RELATIONS**************
+
+relation pas - module :
+p = pi*m
+
+relation pas réel - pas apparent :
+pa = pr/cos(beta)
+
+relation module apparent - module réel :
+ma = mr/cos(beta)
+
+relation angle de pression réel - angle de pression apparent :
+tan(alpha_r) = tan(alpha_a)*cos(beta)
+alpha_a = arctan(tan(alpha_r)/cos(beta))
+
+diamètre primitif :
+d = Z*mr / cos(beta)
+d = Z*ma
+
+diamètre de tête
+D = d + 2*mr
+
+nombre de dent :
+Z = d*cos(beta)/mr
+
+*/
+
+module roue_dentee_helicoidale(z = 40, m = 1, alpha = 20, beta = 60, epaisseur = 10, deport = 0, evider = false)
+{
+	/*le paramètre twist est le nombre de degrés effectué pendant l'extrusion
+
+    pour un schéma détaillé voir :
+    http://www.zpag.net/Machines_Simples/engrenage_droit_dent_helicoidale.htm
+
+	ATTENTION !!
+	Pour engrainer les différentes roues dentées doivent avoir :
+    - le même MODULE RÉEL !!
+    - Le même angle Bêta, pour un contact extérieur : beta1 = -beta2
+                          pour un contact intérieur : beta1 = beta2
+    
+	Or roue_dentee_2D correspond à la coupe transversale de la roue dentée, dans ce plan là il s'agit du module apparent.
+	La conversion se fait grâce à la relation : mr = ma*cos(beta);
+	*/
+    
+    //CALCUL DES PARAMETRES APPARENTS
+	ma = m/cos(beta);
+    alpha_a = atan2(tan(alpha),cos(beta));
+    
+    //CALCUL DU TWIST
+    /*Dans la suite tous les paramètres seront sur le cercle primitif. Pour calculer l'angle de rotation pendant l'extrusion il faut résoudre 2 triangles. Le premier est celui qui part du bord d'une dent à la base de la roue dentée (point A), monte à la verticale sur surface supérieure (point B) et termine sur le point équivalent au point A mais sur la surface supérieure (point C). Le deuxième triangle est OBC avec O le centre de la roue dentée.
+    
+    CARACTÉRISTIQUES CONNUES DE LA FIGURE :
+    0) l'angle BAC = beta
+    1) la distance AB est l'épaisseur de la roue dentée
+    2) les distances OB et OC sont le rayon du cercle primitif
+
+    DÉDUCTIONS :
+    Sachant que AB*tan(beta) = BC et que BC est une corde du cercle alors si on nomme l'angle BOC theta on peut écrire :
+    2*OC*sin(theta/2) = BC. En égalisant les deux relations on obtient :
+    AB*tan(beta) = 2*OC*sin(theta/2)
+    AB*tan(beta)/(2*OC) = sin(theta/2)
+    asin(AB*tan(beta)/(2*OC)) = theta/2
+    2*asin(AB*tan(beta)/(2*OC)) = theta
+    
+    Theta est notre angle de twist. Les notations du script sont :
+    AB = epaisseur
+    beta = beta
+    2*OC = d = z*ma
+    theta = angle
+    
+    On obtient donc : 
+    angle = 2*asin(epaisseur * tan(beta) / (z*ma));
+    Cependant lorsque l'épaisseur devient trop importante alors on sort du domaine de définition de la fonction asin et le résultat devient incohérent. Pour palier à ce problème on va considérer que notre roue dentée est une succession de couches, comme lors d'une impression 3D. De ce fait on peut calculer l'angle entre 2 couches et par une règle de 3 on obtient le twist total.
+    */
+    h = 0.01;   //couches fines
+    gamma = 2*asin(h * tan(beta) / (z*ma));
+	angle = epaisseur*gamma/h;
+	
+	linear_extrude(height = epaisseur, twist = angle)
+	{roue_dentee_2D(z, ma, alpha_a, deport, evider);}
+}
+
+module roue_dentee_helicoidale_globoide(z = 40, m = 1, alpha = 20, beta = 60, epaisseur = 10, deport = 0, evider = false)
+{
+	//CALCUL DES PARAMETRES APPARENTS
+	ma = m/cos(beta);
+	
+	d = ma*z;
+    da = d + 2*ma;
+	
+	difference()
+	{
+		roue_dentee_helicoidale(z, m, alpha, beta, epaisseur, deport, evider);
+		
+		rayon = epaisseur / (2*sin(2*atan2(epaisseur, (da-d))));
+        
+        translate([0, 0, epaisseur/2])
+        {
+            rotate_extrude()
+            {
+                translate([d/2 + rayon, 0, 0])
+                {circle(rayon);}
+            }
+        }
+	}
+}
+
+module roue_dentee_helicoidale_globoide_vis(z = 40, m = 1, alpha = 20, beta = 60, vis_diam = 10, deport = 0, evider = false)
+{
+	//CALCUL DES PARAMETRES APPARENTS
+	ma = m/cos(beta);
+	
+	d = ma*z;
+    da = d + 2*ma;
+	
+	epaisseur = 2*sqrt( pow(vis_diam/2, 2) - pow(vis_diam/2 - ma, 2));
+	
+	difference()
+	{
+		roue_dentee_helicoidale(z, m, alpha, beta, epaisseur, deport, evider);
+		
+        translate([0, 0, epaisseur/2])
+        {
+            rotate_extrude()
+            {
+                #translate([ d/2 + vis_diam/2, 0, 0])
+                {circle(r=vis_diam/2);}
+            }
+        }
+	}
+}
+
+module roue_dentee_chevron(z = 40, m = 1, alpha = 20, beta = 60, epaisseur = 10, deport = 0, evider = false)
+{
+    //CALCUL DES PARAMETRES APPARENTS
+	ma = m/cos(beta);
+    
+    //CALCUL DU TWIST
+    h = 0.1;   //couches fines
+    gamma = 2*asin(h * tan(beta) / (z*ma));
+	angle = epaisseur*gamma/h;
+	
+    roue_dentee_helicoidale(z, m, alpha, beta, epaisseur/2, deport, evider);
+    
+    translate([0, 0, epaisseur/2])
+    {
+        rotate([0, 0, -angle/2])
+        {roue_dentee_helicoidale(z, m, alpha, -beta, epaisseur/2, deport, evider);}
+    }
+}
+
+module roue_dentee_couronne_2D(z = 10, m = 1, alpha = 20, deport = 0, marge = 10)
+{
+	d = m * z;
+	ha = m + deport;
+    da = d + 2*ha;
+	
+	difference()
+	{
+		circle(d = da + marge);
+		roue_dentee_2D(z, m, alpha, deport);
+	}
+	echo("diamètre de la couronne = ", da + marge);
+}
+
+
+/**************ENGRENAGE PLANÉTAIRE**************/
+
+function rayon_satellites(m, zp, zs) = m*(zp + zs)/2;
+function nbr_max_satellites(R, da) = floor(180/asin(da/(2*R)));
+function nbr_satellites_equilibre(zp, zs, nbr) = ceil((zp + zs)/nbr) == (zp + zs)/nbr ? nbr : nbr_satellites_equilibre(zp, zs, nbr - 1);
+
+module planetaire_2D(zp = 33, zs = 27, m = 1, alpha = 26, deport = 0, marge = 10)
+{
+	/*DÉFINITIONS :
+	
+	Planétaires : roue dentée tournant autour d'un axe fixe
+	Satellites : roue dentée tournant autour d'un axe mobile
+	
+	La roue dentée centrale est appelée : planétaire
+	La roue dentée extérieure est appelée : couronne
+	
+	Ce module génère un engrenage planétaire (de type 1) à partir du nombre de dent du planétaire et des satellites,
+	respectivement zp et zs
+	
+	Comme pour tous engrenages, les différentes roues engrènent au niveau de leurs cercles primitifs d.
+	En ce plaçant dans le cas d'un engrenage planétaire composé d'un planétaire, de 2 satellites et
+	d'une couronne, on comprend que le diamètre de la couronne est égale au diamètre du planétaire (dp)
+	plus 2 fois le diamètres d'un satellite (ds).
+	
+	dc = dp + 2*ds
+	
+	Pour que les roues engrènent il est nécessaire qu'elles aient le même module, la formule générale qui lie
+	le diamètre et le nombre de dent est :
+	
+	d = m*z
+	
+	On en déduit :
+	dc = dp + 2*ds
+	<=> m*zc = m*zp + 2*m*zs
+	<=> m*zc = m*(zp + 2*zs)
+	<=> zc = zp + 2*zs
+	
+	CONTRAINTES :
+	
+	1)Pour maximiser le couple transmis, il faut maximiser le nombre de satellites. Cependant il existe une limite pour laquelle
+	les satellites se chevaucheront. Pour touver le nombre de satellites maximum il faut comparer le diamètre de tête d'un satellite,
+	avec la longueur du coté du polygone régulier crée par le centre des satellites.
+	
+	La longueur d'un coté du polygone est :
+	l = 2*R*sin(180/n)
+	avec R le rayon du cercle circonscrit
+	n le nombre de cotés du polygone qui est égal à nbr_satellites
+	
+	Sachant que l > da on peut en déduire :
+	<=> 2*R*sin(180/nbr_satellites) > da
+	<=> sin(180/nbr_satellites) > da/(2*R)
+	<=> 180/nbr_satellites > asin(da/(2*R))
+	<=>180/asin(da/(2*R)) > nbr_satellites
+	<=> nbr_satellites = floor(180/asin(da/(2*R)))
+	
+	On trouve ainsi le nombre maximum de satellites qui permet au train de continuer de fonctionner.
+	
+	2)Connaitre le nombre maximum de satellites possible n'est pas suffisant, faut-il encore que l'engrenage soit équilibré.
+	Pour se faire il faut respecter : 
+	(zp + zs)/nbr_satellites = k, avec k un nombre entier
+	Cette condition permet de déterminer toutes les configurations possible.
+	
+	Exemple : zp = 20, zs = 20
+	La condition nous indique la possibilité d'utiliser :
+	1, 2, 4, 5, 10 ou même 20 satellites.
+	
+	En combinant les 2 conditions on est capable de déterminer le nombre de satellites maximum pour générer un système équilibré.
+	
+	
+	
+		
+	La formule de Willis permet de calculer le rapport de réduction, dans le cas d'un engrenage de type 1 :
+	
+	lambda = zs*zc/zs*zp = zc/zp
+	
+	*/
+	zc = zp + 2*zs;
+	dp = m*zp;
+	ds = m*zs;
+	dc = m*zc;
+	
+	//calcul du rayon sur lequel circulent les satellites
+	rayon = (dp + ds)/2;
+	rapport1 = zc/zp + 1;
+	rapport2 = zc/zs - 1;
+	
+	//on commence par placer le planétaire
+	//les calculs qui suivent permettent d'orienter correctement la roue dentée
+	l1 = pi*dp/(2*zp) + 2*deport*sin(alpha);
+    la1 = 2*degre(l1/dp);
+	db1 = dp * cos(alpha);
+	Idp = intersect(db1, dp);
+    angle1 = atan2( developpante_y(db1/2,Idp), developpante_x(db1/2,Idp));
+	angle_base1 = la1 + 2*angle1;
+	
+	rotate([0, 0, 360*(rapport1)*$t - angle_base1/2.0 + la1 + 180*(zs/zp + 2)])
+	{
+		roue_dentee_2D(z = zp, m = m, alpha = alpha, deport = deport);
+	}
+
+	//puis les satellites
+	//pareil ici
+	l2 = pi*ds/(2*zs) + 2*deport*sin(alpha);
+    la2 = 2*degre(l2/ds);
+	db2 = ds * cos(alpha);
+	Ids = intersect(db2, ds);
+    angle2 = atan2( developpante_y(db2/2,Ids), developpante_x(db2/2,Ids) );
+    angle_base2 = la2 + 2*angle2;
+	
+	nbr_satellites = nbr_satellites_equilibre(zp, zs, nbr_max_satellites(rayon_satellites(m, zp, zs), m*zs+2*(m+deport)));
+	
+	
+	if( ceil((zp + zs)/nbr_satellites) == (zp + zs)/nbr_satellites)
+	{
+		for(i=[1:nbr_satellites])
+		{
+			translate([ rayon*cos(360*$t + 360*i/nbr_satellites), rayon*sin(360*$t + 360*i/nbr_satellites), 0])
+			{
+				rotate([0, 0, -360*rapport2*$t - angle_base2/2 - 360*i/nbr_satellites * rapport2])
+				{roue_dentee_2D(z = zs, m = m, alpha = alpha, deport = deport);}
+			}
+		}
+	}
+
+	//et enfin on place la couronne
+	//et pareil là
+	lc = pi*dc/(2*zc) + 2*deport*sin(alpha);
+    lac = 2*degre(lc/dc);
+	dbc = dc * cos(alpha);
+	Idc = intersect(dbc, dc);
+    anglec = atan2( developpante_y(dbc/2,Idc), developpante_x(dbc/2,Idc) );
+    angle_basec = lac + 2*anglec;
+	
+	rotate([0, 0, -angle_basec/2])
+	{roue_dentee_couronne_2D(z = zc, m = m, alpha = alpha, deport = deport, marge = marge);}
+	
+	echo("nombre de dent de la couronne = ", zc);
+	echo("rapport = ", zc/zp);
+	echo(nbr_satellites = nbr_satellites);
+}

+ 272 - 0
math.scad

@@ -0,0 +1,272 @@
+/***********************************CONSTANTES***********************************/
+pi = 3.1415926535;
+
+/***********************************ARITHMÉTIQUE***********************************/
+function PGCD(a,b) = a > b ? PGCD(b , a-b) : a < b ? PGCD(a, b-a) : a;
+
+/**********************************************************************************/
+/***********************************GEOMETRIE***********************************/
+/**********************************************************************************/
+
+/***********************************FONCTIONS 2D***********************************/
+//CONVERSION
+function rad(angle = 0) = pi * angle / 180;
+function degre(angle = 0) = angle * 180 / pi;
+
+function calcule_distance_2d(x, y) = sqrt(pow(x, 2) + pow(y, 2));
+
+function milieu( A, B) = [ (A[0] + B[0])/2, (A[1] + B[1])/2 ];
+
+/***************************************************************************************
+calcul de l'angle formé par la droite OA avec A[x, y] et l'axe des abscisses
+pour connaitre le sens de l'angle il faut vérifier si y est positif ou négatif
+pour éviter les divisions par 0 il faut vérifier si y == 0
+***************************************************************************************/
+//function calcule_angle_2d(x, y) = y < 0 ? 360-acos(x/calcule_distance_2d(x, y)) : y == 0 && x>=0 ? 0 : acos(x/calcule_distance_2d(x, y)); 
+function calcule_angle_2d(x, y) = y < 0 ? 360-acos(x/calcule_distance_2d(x, y)) : y > 0 ? acos(x/calcule_distance_2d(x, y)) : x>=0 ? 0 : 180; 
+
+/******************************DEVELOPPANTE DE CERCLE******************************/
+function developpante_x(r = 1, t = 0) = r*(cos(t)+rad(t)*sin(t));
+function developpante_y(r = 1, t = 0) = r*(sin(t)-rad(t)*cos(t));
+
+//INTERSECTION
+/*On cherche à calculer le point d'intersection
+d'une développante de cercle et d'un cercle.
+Pour se faire il faut chercher la valeur du paramètre a dans les équations :
+x(a) = r*(cos(a) + a*sin(a))
+y(a) = r*(sin(a) - a*cos(a))
+
+En utilisant pythagore on conclue que le paramètre doit satisfaire :
+tel que x(a)² + y(a)² = R²
+avec R le rayon du cercle que coupe la développante.
+
+[r*(cos(a) + a*sin(a))]² + [r*(sin(a) - a*cos(a))]² = R²
+r² * (cos(a) + a*sin(a))² + r² * (sin(a) - a*cos(a))² = R²
+
+On peut factoriser par r²
+r² * [ (cos(a) + a*sin(a))² + (sin(a) - a*cos(a))² ] = R²
+(cos(a) + a*sin(a))² + (sin(a) - a*cos(a))² = R²/r²
+
+On utilise les identitées remarquables :
+cos(a)² + 2a*cos(a)*sin(a) + a²*sin(a)² + sin(a)² - 2a*cos(a)*sin(a) + a²*cos(a)² = R²/r²
+cos(a)² + a²*sin(a)² + sin(a)² + a²*cos(a)² = R²/r²
+cos(a)² + sin(a)² + a²*sin(a)² + a²*cos(a)² = R²/r²
+cos(a)² + sin(a)² + a²*( sin(a)² + cos(a)² ) = R²/r²
+
+Sachant que cos² + sin² = 1 on obtient :
+1 + a² = R²/r²
+a² = R²/r² - 1
+a = sqrt(R²/r² - 1)
+*/
+
+function intersect_rad(r=1, R=2) = sqrt( (R*R)/(r*r) - 1);
+function intersect(r=1, R=2) = degre(intersect_rad(r, R));
+
+/***********************************FONCTIONS 3D***********************************/
+function projection_xy(vecteur) = [vecteur[0], vecteur[1], 0];
+
+function conversion_cartesien_spherique(vecteur) =
+[norm(vecteur),
+norm(projection_xy(vecteur)) == 0 ? 0 : vecteur[1] < 0 ? 360-acos(vecteur[0]/norm(projection_xy(vecteur))) : acos(vecteur[0]/norm(projection_xy(vecteur))),
+acos(vecteur[2]/norm(vecteur))];
+
+/***********************************MODULES***********************************/
+
+/***************************************************************************************
+Modules pour créer une spirale
+
+spirale_coord prend en arguments :
+x1 l'abscisse du point de départ
+y1 l'ordonnée du point de départ
+x2 l'abscisse du point d'arrivé
+y2 l'ordonnée du point d'arrivé
+tour désigne le nombre de tour qui devront être effectué pour passer du point de départ au point d'arrivé
+largeur désigne la largeur du bras de la spirale
+
+spirale_point prend en arguments:
+A un vecteur représentant le point de départ
+B un vecteur représentant le point d'arrivé
+tour désigne le nombre de tour qui devront être effectué pour passer du point de départ au point d'arrivé
+largeur désigne la largeur du bras de la spirale
+
+**********************************************************************************/
+module spirale_coord(x1 = 10, y1 = 0, x2 = 10, y2 = 10, tours = 2, largeur = 1)
+{
+    //calcule des distances par rapport à l'origine
+    d1 = calcule_distance_2d(x1, y1);
+    d2 = calcule_distance_2d(x2, y2);
+    
+    //calcule des angles entre les vecteur OA et Ox
+    theta1 = calcule_angle_2d(x1, y1);
+    theta2 = calcule_angle_2d(x2, y2);
+    
+    //calcule de l'angle à balayer pour effectuer le nombre de tour voulu
+    //pour lier le point de départ et le point d'arrivé
+    angle = tours * 360 + (theta2 - theta1);
+    
+    //la spirale est de type linéaire, cela signifie que le rayon de la courbe va croitre de manière proportionnelle à l'angle
+    coeff_dir = (d2 - d1)/angle;
+    
+    //création des points extérieur de la spirale du point de départ vers le point d'arrivé
+    A = [for(i=[0:1:angle])
+        [(coeff_dir * i + d1 + largeur/2) * cos(i + theta1),
+         (coeff_dir * i + d1 + largeur/2) * sin(i + theta1)]];
+    
+    //création des points interieur de la spirale du point d'arrivé vers le point de départ
+    B = [for(i=[angle:-1:0])
+        [(coeff_dir * i + d1 - largeur/2) * cos(i + theta1),
+         (coeff_dir * i + d1 - largeur/2) * sin(i + theta1)]];
+    
+    //combinaison des 2 séries de points
+    C = concat(A,B);
+    
+    //tracé de la courbe finale
+    polygon(C);
+}
+
+module spirale_coord2(x1 = 0, y1 = 0, x2 = 0, y2 = 10, tours = 2, largeur = 1)
+{
+    /*pour une spirale linéaire, ou d'Archimède, la relation est la suivante :
+    r = a + b*theta
+    cela signifie que les coordonnées cartésiennes sont :
+    x(theta) = r*cos(theta) = (a + b*theta)*cos(theta)
+    y(theta) = r*sin(theta) = (a + b*theta)*sin(theta)
+    */
+    function delta_x(t = 0) = cos(t) - rad(t)*sin(t);
+    function delta_y(t = 0) = sin(t) + rad(t)*cos(t);
+    
+    //calcule des distances par rapport à l'origine
+    d1 = calcule_distance_2d(x1, y1);
+    d2 = calcule_distance_2d(x2, y2);
+    
+    //calcule des angles entre les vecteur OA et Ox
+    theta1 = calcule_angle_2d(x1, y1);
+    theta2 = calcule_angle_2d(x2, y2);
+    
+    //calcule de l'angle à balayer pour effectuer le nombre de tour voulu
+    //pour lier le point de départ et le point d'arrivé
+    angle = tours * 360 + abs(theta2 - theta1);
+        
+    //la spirale est de type linéaire, cela signifie que le rayon de la courbe va croitre de manière proportionnelle à l'angle
+    coeff_dir = (d2 - d1)/angle;
+    
+    function vecteur(t = 0) = [[0, -1],[1,  0]]*[delta_x(t = t), delta_y(t = t)]/norm([delta_x(t = t), delta_y(t = t)]);
+//    function vecteur(t = 0) = [largeur*cos(t)/2, largeur*sin(t)/2];
+    
+    //création des points extérieur de la spirale du point de départ vers le point d'arrivé
+    A = [for(i=[0:1:angle])
+        (coeff_dir * i + d1) * [cos(i + theta1), sin(i + theta1)] + vecteur(t = i + theta1) ];
+    
+    //création des points interieur de la spirale du point d'arrivé vers le point de départ
+    B = [for(i=[angle:-1:0])
+        (coeff_dir * i + d1) * [cos(i + theta1), sin(i + theta1)] - vecteur(t = i + theta1) ];
+    
+    //combinaison des 2 séries de points
+    C = concat(A,B);
+    
+    //tracé de la courbe finale
+    polygon(C);
+}
+
+module spirale_log_coord(x1 = 1, y1 = 0, x2 = 20, y2 = 0, tours = 2, largeur = 1)
+{
+    //calcule des distances par rapport à l'origine
+    d1 = calcule_distance_2d(x1, y1);
+    d2 = calcule_distance_2d(x2, y2);
+    
+    //calcule des angles entre les vecteur OA et Ox
+    theta1 = calcule_angle_2d(x1, y1);
+    theta2 = calcule_angle_2d(x2, y2);
+	
+	echo("<font color='#ffa400'>math.scad, module : spirale_log_coord</font>");
+	echo("<font color='#ffa400'>theta1 = ", theta1, "</font>");
+	echo("<font color='#ffa400'>theta2 = ", theta2, "</font>");
+    
+    //calcule de l'angle à balayer pour effectuer le nombre de tour voulu
+    //pour lier le point de départ et le point d'arrivé
+    delta_theta = theta2 - theta1 >= 0 ? theta2 - theta1 : 360 - (theta1 - theta2);
+//    angle = tours * 360 - theta1 + theta2;
+    angle = tours * 360 + delta_theta;
+    theta2_ = angle + theta1;
+    
+	echo("<font color='#ffa400'>angle = ", angle, "</font>");
+
+    /*une spirale logarithmique est décrite par : r = a*b^theta
+    Si on possède 2 points :
+    r1 = a*b^theta1
+    r2 = a*b^theta2
+    on peut extraire le coefficient a :
+    ln(r1) = ln(a*b^theta1) = ln(a) + ln(b^theta1) = ln(a) + theta1*ln(b)
+    ln(r2) = ln(a*b^theta2) = ln(a) + ln(b^theta2) = ln(a) + theta2*ln(b)
+    
+    ln(r2) - ln(r1) = ln(a) - ln(a) + theta2*ln(b) - theta1*ln(b)
+    ln(r2/r1) = ln(b) * (theta2 - theta1)
+    ln(r2/r1)/(theta2-theta1) = ln(b)
+    <=> b = exp( ln(r2/r1)/(theta2-theta1) )
+    
+    */
+    b = exp( ln(d2/d1)/(theta2_-theta1) );
+    a = d1/(pow(b,theta1));
+    
+    //création des points extérieur de la spirale du point de départ vers le point d'arrivé
+    A = [for(i=[0:1:angle])
+        [(a*pow(b,(i + theta1)) + largeur/2) * cos(i + theta1),
+         (a*pow(b,(i + theta1)) + largeur/2) * sin(i + theta1)]];
+
+    //création des points interieur de la spirale du point d'arrivé vers le point de départ
+    B = [for(i=[angle:-1:0])
+        [(a*pow(b,(i + theta1)) - largeur/2) * cos(i + theta1),
+         (a*pow(b,(i + theta1)) - largeur/2) * sin(i + theta1)]];
+    
+    //combinaison des 2 séries de points
+    C = concat(A,B);
+    
+    //tracé de la courbe finale
+    polygon(C);
+}
+
+//spirale_coord2(x1 = 2.5, y1 = 0, x2 = 20, y2 = 0, tours = 2, largeur = 1);
+
+module spirale_point(A = [0, 0], B = [10, 10], tours = 1, largeur = 1)
+{
+    spirale(A[0], A[1], B[0], B[1], tours, largeur);
+}
+
+module polygone_regulier(cotes = 5, rayon = 10)
+{
+    polygon([for(i=[0: 360/cotes : 360])[rayon * cos(i), rayon * sin(i)]]);
+}
+
+module portion_disque(rayon = 10, angle = 180)
+{
+    A = [for(i=[0 : 1 : angle])[rayon * cos(i), rayon * sin(i)]];
+    B = concat([[0, 0]], A);
+    polygon(B);
+}
+
+module gaussienne(sigma = 0.5, mu = 0, interval = 20)
+{
+    polygon([   for(i=[-interval/2:0.1:interval/2])[i,  exp(-pow( (i - mu),2))/(2*pow(sigma,2))/(sigma * sqrt(2*pi))    ] ]);
+}
+
+
+module trompette(epaisseur = 2, hauteur = 10, r_min = 20, r_max = 40, precision = 100, facteur = 1)
+{
+	x1 = ln(hauteur/(exp( facteur * (r_max - r_min)) - 1))/facteur;
+	x2 = r_max - r_min + x1;
+	
+	function calcule_xb(xa, l) = -sqrt(pow(l, 2)/(1 + facteur * facteur * exp(-2*xa * facteur))) + xa;
+	function calcule_yb(xa, l) = sqrt(pow(l, 2)/(1 + facteur * facteur * exp(2*xa * facteur))) + exp(facteur * xa);
+	
+	A = [for(i=[x1:(x2-x1)/precision:x2])	[i ,exp(facteur *i)]]; 
+	B = [for(i=[x2:-(x2-x1)/precision:x1])	[calcule_xb(i, epaisseur), calcule_yb(i, epaisseur)]];
+		
+	C = concat(A,B);
+	
+	
+	rotate_extrude()
+	{
+		translate([  -x2 - r_min, -exp(facteur * x1), 0])
+		{polygon(C);}
+	}
+}

+ 105 - 0
meca.scad

@@ -0,0 +1,105 @@
+include <math.scad>
+
+/***************************************************************************************
+Modules pour créer un ressort spirale
+
+ressort_coord prend en arguments :
+x1 l'abscisse du point de départ
+y1 l'ordonnée du point de départ
+x2 l'abscisse du point d'arrivé
+y2 l'ordonnée du point d'arrivé
+tour désigne le nombre de tour qui devront être effectué pour passer du point de départ au point d'arrivé
+largeur désigne la largeur du bras de la spirale
+hauteur
+fix_int désigne le diamètre interne du trou de fixation
+fix_ext désigne le diamètre externe de la fixation
+
+ressort_point prend en arguments:
+A un vecteur représentant le point de départ
+B un vecteur représentant le point d'arrivé
+tour désigne le nombre de tour qui devront être effectué pour passer du point de départ au point d'arrivé
+largeur désigne la largeur du bras de la spirale
+hauteur
+fix_int désigne le diamètre interne du trou de fixation
+fix_ext désigne le diamètre externe de la fixation
+
+***************************************************************************************/
+module ressort_coord(x1 = -10, y1 = -10, x2 = -30, y2 = -30, tours = 2, largeur = 1, hauteur = 2, fix_int = 3, fix_ext = 5)
+{
+    difference()
+    {
+        union()
+        {
+            //création des fixations
+            //point de départ
+            translate([x1, y1])
+            {cylinder(d = fix_ext, h = hauteur);}
+            
+            //point d'arrivé
+            translate([x2, y2])
+            {cylinder(d = fix_ext, h = hauteur);}
+            
+            //création de la spirale
+            theta2 = calcule_angle_2d(x2, y2);
+
+            theta1 = norm([x1, y1]) == 0 ? theta2 - tours * 360 : calcule_angle_2d(x1, y1);
+            linear_extrude(hauteur)
+            {
+                spirale_log_coord(
+                x1 + ((fix_ext - largeur)/2 ) * cos(theta1),
+                y1 + ((fix_ext - largeur)/2 ) * sin(theta1),
+                x2 + ((fix_ext - largeur)/2 ) * cos(theta2),
+                y2 + ((fix_ext - largeur)/2 ) * sin(theta2),
+                tours, largeur);
+            }    
+        }
+        
+        //création des trous de fixations
+        //point de départ
+        translate([x1, y1, -0.5])
+        {cylinder(d = fix_int, h = hauteur + 1);}
+        
+        //point d'arrivé
+        translate([x2, y2, -0.5])
+        {cylinder(d = fix_int, h = hauteur + 1);}
+    }
+}
+
+module ressort_point(A = [0, 0], B = [10, 10], tours = 2, largeur = 1, hauteur = 2, fix_int = 3, fix_ext = 5)
+{
+    ressort_coord(A[0], A[1], B[0], B[1], tours, largeur, hauteur, fix_int, fix_ext);
+}
+
+/***************************************************************************************
+Modules pour les écrous
+https://fr.wikipedia.org/wiki/%C3%89crou_hexagonal
+***************************************************************************************/
+module ecrou(largeur, hauteur)
+{
+    linear_extrude(hauteur)
+    {polygone_regulier(cotes = 6, rayon = largeur/sqrt(3));}
+}
+
+module ecrou_M1(marge = 0.5, marge_h = 0, h = 0.8)
+{ecrou(largeur = 2.5 + marge, hauteur = h + marge_h);}
+
+module ecrou_M2(marge = 0.5, marge_h = 0, h = 1.6)
+{ecrou(largeur = 4 + marge, hauteur = h + marge_h);}
+
+module ecrou_M3(marge = 0.5, marge_h = 0, h = 2.4)
+{ecrou(largeur = 5.5 + marge, hauteur = h + marge_h);}
+
+module ecrou_M4(marge = 0.5, marge_h = 0, h = 3.2)
+{ecrou(largeur = 7 + marge, hauteur = h + marge_h);}
+
+module ecrou_M5(marge = 0.5, marge_h = 0, h = 4.7)
+{ecrou(largeur = 8 + marge, hauteur = h + marge_h);}
+
+module ecrou_M6(marge = 0.5, marge_h = 0, h = 5.2)
+{ecrou(largeur = 10 + marge, hauteur = h + marge_h);}
+
+module ecrou_M8(marge = 0.5, marge_h = 0, h = 6.8)
+{ecrou(largeur = 13 + marge, hauteur = h + marge_h);}
+
+module ecrou_M10(marge = 0.5, marge_h = 0, h = 8.4)
+{ecrou(largeur = 17 + marge, hauteur = h + marge_h);}

+ 38 - 0
pavage.scad

@@ -0,0 +1,38 @@
+module pavage_hexagonal(r1 = 15, r2 = undef, epaisseur = 2, espace = 2, x = 25, y = 40, center = false)
+{
+    r2 = r2 == undef ? r1 : r2;
+    
+    /*la longueur d'un motif sur l'axe y est très facile à calculer :
+    hauteur de l'héxagone + espace
+    long = r1*sqrt(3) + espace
+    
+    la longueur sur l'axe x est plus complexe.
+    l = (r1 + r1*cos(60) + espace*cos(30))*n - r1*cos(60)
+    (l + r1*cos(60))/(r1 + r1*cos(60) + espace*cos(30)) = n
+    */
+    
+    long = sqrt(3)*r1 + espace;
+    
+    nbr_x = floor( (x + r1*cos(60))/(r1 + r1*cos(60) + espace*cos(30)));
+    nbr_y = ceil(y/long) - 1;
+    
+    delta_x = center ? -((r1 + r1*cos(60) + espace*cos(30))*(nbr_x))/2 + r1*cos(60) - r1: 0;
+    delta_y = center ? -(nbr_y + 1) * long/2 + espace/2 : 0;
+    
+    echo(delta_x=delta_x);
+
+    translate([delta_x, delta_y, 0])
+    {
+        for(i = [0:nbr_x])
+        {
+            for(j = [0:nbr_y + i%2])
+            {
+                translate([i*cos(30)*long + r1*cos(60), j*long + r1*sin(60) - sin(30)*long*(i%2), 0])
+                {
+                    linear_extrude(epaisseur, scale = r2/r1)
+                    {polygon([for(k=[0:60:360])[r1*cos(k), r1*sin(k)]]);}
+                }
+            }
+        }
+    }
+}

+ 54 - 0
symbole.scad

@@ -0,0 +1,54 @@
+$fn=100;
+function points(rayon, angle) = [rayon*cos(angle), rayon*sin(angle)];
+
+module triangle(rayon)
+{polygon([points(rayon, -30), points(rayon, 90), points(rayon, 210)]);}
+
+module triangle_arrondi(rayon)
+{
+	minkowski()
+	{
+		triangle(rayon);
+		circle(rayon/5);
+	}
+}
+
+module symbole(taille, numero, texte)
+{
+	union()
+	{
+		difference()
+		{
+			offset(r = taille/5)
+			{triangle_arrondi(taille);}
+			
+			triangle_arrondi(taille);
+			
+			for(i=[0:2])
+			{
+				rotate([0, 0, 30 + i*120])
+				{
+					translate([taille/2 + taille/5 - 0.1, -taille/5, 0])
+					{square([taille/5 + 0.2, 2*taille/5]);}
+				}
+			}
+		}
+	
+		for(i=[0:2])
+		{
+			rotate([0, 0, 30 + i*120])
+			{
+				translate([12*taille/15, taille/8, 0])
+				{
+					rotate([0, 0, 60])
+					{triangle(taille/3);}
+				}
+			}
+		}
+		
+		text(numero, valign="center", halign="center", size=taille/1.4);
+		
+		translate([0, -6*taille/5, 0])
+		{text(texte, valign="top", halign="center", size=taille/1.4);}
+	}
+}

+ 121 - 0
vis.scad

@@ -0,0 +1,121 @@
+/*la variable pas contient les pas des vis métrique
+p[1] = pas d'une vis M1, p[2] = pas d'une vis M2 etc ...
+!!!!! ATTENTION !!!!!
+les vis M7 n'éxistent pas p[7] = -1
+idem pour 9, 11, 13, 15, 17 etc ...
+*/
+
+
+
+/* profil de la vis
+
+       B ___C          B ___
+        /     \          /
+       /       \        /
+ ____/         \____/
+      A        D		A
+	  -----> +Z
+*/
+
+//function limite_haute(i, p, h, k) = i*p/360 - p + k < h ? i*p/360 - p + k : h;
+//function hauteur( i, p, h, k) =  i*p/360 - p + k < 0 ? 0 : limite_haute(i, p, h, k);
+
+module vis(diam_int = 4, diam_ext = 6, DA = 0.25, BC = 0.25, pas = 1, haut = 10, precision = 5, diam_buse = 0.4)
+{
+	/*Lors de l'impression le centre de la buse se placera au bon endroit
+	ce qui signifie qu'une erreur de la moitié du diamètre de la buse apparaitra à l'extérieur.
+	*/
+	d1 = diam_int - diam_buse;
+	d2 = diam_ext - diam_buse;
+	
+	//ajout de 2 tour pour avoir une coupe propre lors de la création de la vis
+	nbr_tours = ceil(haut/pas) + 2;
+	angle = nbr_tours * 360;
+
+	//par symétrie AB = CD
+	AB = pas/2 - BC/2 - DA/2;
+	
+	A = [ for(i=[0 : precision : angle]) [ d1*cos(i)/2, d1*sin(i)/2, i*pas/360 - pas ] ] ;
+	B = [ for(i=[0 : precision : angle]) [ d2*cos(i)/2, d2*sin(i)/2, i*pas/360 - pas + AB ] ];
+	C = [ for(i=[0 : precision : angle]) [ d2*cos(i)/2, d2*sin(i)/2, i*pas/360 - pas + AB + BC] ];
+	D = [ for(i=[0 : precision : angle]) [ d1*cos(i)/2, d1*sin(i)/2, i*pas/360 - pas + AB + BC + AB] ];
+
+	points = concat(A, B, C, D, [[0, 0, 0]], [[0, 0, nbr_tours * pas]]);
+	
+	longueur = len(A);
+	index_A = 0;
+	index_B = longueur;
+	index_C = index_B + longueur;
+	index_D = index_C + longueur;
+	index_O = index_D + longueur;
+	index_Oh = index_O + 1;
+	
+	faces_inferieurs1 = [ for(i=[0:longueur - 2]) [ index_A + i, index_B + i, index_A + 1 + i ] ];
+	faces_inferieurs2 = [ for(i=[0:longueur - 2]) [ index_B + i, index_B + 1 + i, index_A + 1 + i ] ];
+	faces_exterieurs1 = [ for(i=[0:longueur - 2]) [ index_B + 1+ i, index_B + i, index_C + i ] ];
+	faces_exterieurs2 = [ for(i=[0:longueur - 2]) [ index_C + i, index_C + 1 + i, index_B + 1 + i ] ];
+	faces_superieurs1 = [ for(i=[0:longueur - 2]) [ index_C + 1 + i, index_C + i, index_D + i ] ];
+	faces_superieurs2 = [ for(i=[0:longueur - 2]) [ index_D + i, index_D + 1 + i, index_C + 1 + i ] ];
+	faces_interieurs1 = [ for(i=[0:longueur - 2 - 360/precision]) [ index_D + i, index_A + 360/precision + i, index_D + 1 + i ] ];
+	faces_interieurs2 = [ for(i=[0:longueur - 2 - 360/precision]) [ index_A + 360/precision + i, index_A + 360/precision + 1 + i,  index_D + 1 + i ] ];
+		
+	/*!!!!! ATTENTION !!!!!
+	pour éviter l'erreur : Object may not be a valid 2-manifold and may need repair!
+	il faut que les points utilisés pour les disques aient été utilisés dans les autres faces.
+	*/
+	faces_disque_inferieur = [ for(i=[0 : 360/precision - 1]) [ index_A + i, index_A + 1 + i,  index_O ] ];
+	faces_disque_superieur = [ for(i=[0 : 360/precision - 1]) [ index_D + len(D) - 360/precision + i, index_D + len(D) - 360/precision - 1 + i,  index_Oh ] ];
+	face_fermeture_basse = [ [index_O, index_A + 360/precision, index_D, index_C, index_B, index_A] ];
+	face_fermeture_haute = [ [index_Oh, index_D + len(D) - 360/precision - 1, index_A + len(A) - 1, index_B + len(B) - 1, index_C + len(C) - 1, index_D + len(D) - 1] ];
+	faces = concat( faces_inferieurs1, faces_inferieurs2,
+					faces_exterieurs1, faces_exterieurs2,
+					faces_superieurs1, faces_superieurs2,
+					faces_interieurs1, faces_interieurs2,
+					faces_disque_inferieur,	faces_disque_superieur,
+					face_fermeture_basse, face_fermeture_haute
+					);
+
+	difference()
+	{
+		polyhedron(points, faces);
+		
+		translate([0, 0, -pas])
+		{cylinder(d = 2*d2, h = pas);}
+		translate([0, 0, haut])
+		{cylinder(d = 2*d2, h = 3*pas);}
+	}
+}
+
+module vis_metrique(d = 4, haut = 10, precision = 5, diam_buse = 0.4)
+{
+	//   			     0    1     2     3     4     5     6     7     8     9
+	pas_metrique = [ -1.0, 0.25, 0.40, 0.50, 0.70, 0.80, 1.00, -1.0, 1.25, -1.0,
+					  1.50, -1.0, 1.75, -1.0, 2.00, -1.0, 2.00, -1.0, 2.50, -1.0,
+					  2.50];
+	
+	H = 0.866*pas_metrique[d];
+	d1 = d - 1.0825*pas_metrique[d];
+	if(pas_metrique[d] != -1)
+	{
+		vis(diam_int = d1, diam_ext = d, DA = pas_metrique[d]/4, BC = pas_metrique[d]/8, pas = pas_metrique[d], haut = haut, precision = precision, diam_buse = diam_buse);
+	}
+	else
+	{
+		echo("<font color='red'><b>mauvais diamètre pour la vis métrique</b></font>");
+	}
+}
+
+module vis_sans_fin(m = 1, alpha = 20, diam = 15, haut = 10, precision = 5, diam_buse = 0.4)
+{
+	//hauteur d'une dent
+	hf = m <= 1.25 ? 1.4*m : 1.25*m;
+	ha = m;
+	h = hf + ha;
+
+	p = m*PI;
+	
+	largeur_base = 2*hf*tan(alpha) + p/2;
+	largeur_crete = largeur_base - 2*h*tan(alpha);
+	
+	vis(diam_int = diam, diam_ext = diam + 2*h, DA = p - largeur_base, BC = largeur_crete, pas = p, haut = haut, precision = precision, diam_buse = diam_buse);
+}