// Reproduction des "Russian Doll Maze" d'origines, // avec une fermeture différente. // C.f. : https://www.thingiverse.com/thing:2607374 // Russian Doll Maze Puzzle Box by 3DFabXYZ October 26, 2017 // C.f. : http://openscad.org/documentation.html // Les 4 boîtes sont définie dans ce fichier. // Indique la boite que l'on désire créer // À modifier de 1 à 4 pour choisir la boite à créer. nBoite = 1; // Nombre de boites au total, // La boite 1 est celle le plus à l'intérieure // La boite "nBoiteMax" est la plus grande, à l'extérieur, sans labyrinthe nBoiteMax = 4; // Paramètres globaux des cylindres //================================= // Variante d'épaisseur de référence Size = 2.5; // Distance entre le milieu d'un chemin et le milieu du mur // 2 * Size = disance entre deux chemins voisins. // Différence de rayon entre un cylindre et le suivant. RayonDifference = 4.8; // == Size * 6 / 3.14159265 // Différence entre le rayon intérieur du cylindre qui contient le cylindre en cours // et le rayon extérieur du cylindre en cours de traitement RayonDelta = 0.4; //RayonCylExt = Size * 2 * nbSeparationVerticales / (2 * 3.14159265); // Rayon du cylindre // Rayon extérieur du cylindres 1. Les autres se calculent à partir de lui RayonCylExt01 = 11.1; // Rayon du cylindre, un multiple entier de 0.1 mm // Hauteur totale de la base Htot_Base = 8.0; // hauteur de la base // Données de la base Hchampfer_Base = 1.0; // Partie de base en biais "Champfer" // Épaisseur du fond de la base BaseEpaisseur = 1.8; // Liste de liste de points du labyrinthe 01, le plus à l'intérieur // La première liste de coordonnées d'un "Pathsxx" indique le chemin à suivre Paths01 = [ [ [14, -1], [14, 6], [12, 6], [12, 8], [10, 8], [10, 6], [ 8, 6] , [ 8, 10], [ 6, 10], [ 6, 12], [10, 12], [10, 14], [ 4, 14], [ 4, 16] , [ 8, 16], [ 8, 20], [18, 20], [18, 22], [20, 22], [20, 24], [16, 24] , [16, 26] ] ,[ [14, 6], [16, 6] ] ,[ [12, 6], [12, 2], [10, 2], [10, 4] ] ,[ [12, 8], [18, 8], [18, 4], [20, 4], [20, 8] ] ,[ [ 8, 6], [ 8, 2], [ 2, 2], [ 2, 0] ] ,[ [10, 12], [10, 10] ] ,[ [ 4, 14], [ 2, 14], [ 2, 12], [ 0, 12], [ 0, 14] ] ,[ [ 4, 16], [ 0, 16], [ 0, 18] ] ,[ [ 4, 16], [ 4, 18] ] ,[ [ 8, 16], [10, 16] ] ,[ [ 8, 20], [ 6, 20], [ 6, 18] ] ,[ [10, 20], [10, 22], [12, 22] ] ,[ [10, 20], [10, 18] ] ,[ [14, 20], [14, 24], [ 8, 24], [ 8, 22] ] ,[ [16, 20], [16, 18] ] ,[ [16, 24], [16, 22] ] ,[ [16, 8], [16, 10], [12, 10], [12, 18] ] ,[ [ 4, 2], [ 4, 0], [12, 0] ] ,[ [ 2, 2], [ 2, 4] ] ,[ [ 2, 12], [ 4, 12] ] ,[ [16, 10], [18, 10] ] ]; // ,[, ], [, ], [, ], [, ], [, ], [, ] // Liste de liste de points du labyrinthe 02 Paths02 = [ [ [20, -1], [20, 0], [26, 0], [26, 4], [18, 4], [18, 0], [14, 0] , [14, 2], [12, 2], [12, 0], [ 8, 0], [ 8, 2], [10, 2], [10, 4] , [ 8, 4], [ 8, 8], [10, 8], [10, 6], [16, 6], [16, 10], [18, 10] , [18, 12], [20, 12], [20, 18], [22, 18], [22, 20], [26, 20], [26, 24] , [28, 24], [28, 18], [34, 18], [34, 20], [32, 20], [32, 24], [30, 24] , [30, 26] ] ,[ [20, 0], [20, 2], [24, 2] ] ,[ [26, 4], [26, 8] ] ,[ [18, 4], [16, 4], [16, 2] ] ,[ [12, 2], [12, 4], [14, 4] ] ,[ [14, 6], [14, 8], [12, 8] ] ,[ [16, 8], [18, 8], [18, 6], [24, 6], [24, 8], [20, 8] ] ,[ [16, 10], [16, 14], [ 8, 14], [ 8, 16], [ 6, 16], [ 6, 10], [ 4, 10] , [ 4, 12], [ 2, 12], [ 2, 10] ] ,[ [18, 10], [20, 10] ] ,[ [18, 12], [18, 18], [16, 18], [16, 22] ] ,[ [20, 16], [24, 16] ] ,[ [20, 18], [20, 20], [18, 20], [18, 22], [20, 22] ] ,[ [22, 18], [24, 18] ] ,[ [22, 20], [22, 24], [18, 24] ] ,[ [28, 20], [30, 20] ] ,[ [34, 20], [34, 24], [36, 24] ] ,[ [30, 24], [30, 22] ] ,[ [12, 14], [12, 16], [10, 16] ] ,[ [ 6, 16], [ 6, 18] ] ,[ [ 6, 12], [14, 12], [14, 10], [ 8, 10] ] ,[ [22, 16], [22, 14], [24, 14] ] ,[ [22, 24], [24, 24], [24, 22] ] ,[ [12, 16], [16, 16] ] ]; // ,[ [, ], [, ], [, ], [, ], [, ], [, ] ] // Liste de liste de points du labyrinthe 03 Paths03=[ [ [26, -1], [26, 2], [28, 2], [28, 4], [30, 4], [30, 0], [32, 0] , [32, 6], [26, 6], [26, 10], [28, 10], [28, 8], [34, 8], [34, 4] , [38, 4], [38, 6], [42, 6], [42, 8], [40, 8], [40, 10], [42, 10] , [42, 12], [44, 12], [44, 22], [46, 22], [46, 18], [48, 18], [48, 20] , [52, 20], [52, 22], [48, 22], [48, 26], [44, 26], [44, 28] ] ,[ [28, 2], [28, 0] ] ,[ [32, 0], [38, 0] ] ,[ [26, 6], [26, 4] ] ,[ [26, 8], [24, 8], [24, 4], [18, 4], [18, 10] ] ,[ [26, 10], [24, 10] ] ,[ [28, 10], [28, 12], [20, 12], [20, 8], [22, 8], [22, 6], [20, 6] ] ,[ [34, 4], [34, 2], [42, 2], [42, 0], [40, 0] ] ,[ [42, 6], [42, 4] ] ,[ [40, 8], [36, 8], [36, 6] ] ,[ [42, 12], [42, 14] ] ,[ [44, 16], [42, 16], [42, 20] ] ,[ [44, 22], [42, 22], [42, 24] ] ,[ [48, 18], [52, 18], [52, 14], [48, 14], [48, 16], [46, 16], [46, 14] ] ,[ [52, 20], [56, 20], [56, 24], [54, 24], [54, 22] ] ,[ [52, 22], [52, 26], [60, 26] ] ,[ [50, 22], [50, 26] ] ,[ [44, 26], [44, 24], [46, 24] ] ,[ [22, 4], [22, 0], [20, 0], [20, 2], [18, 2], [18, 0] ] ,[ [28, 12], [32, 12], [32, 10], [38, 10] ] ,[ [22, 8], [22, 10] ] ,[ [40, 2], [40, 4] ] ,[ [52, 14], [58, 14] ] ,[ [48, 16], [50, 16] ] ,[ [22, 0], [24, 0], [24, 2] ] ,[ [30, 12], [30, 10] ] ,[ [34, 10], [34, 16], [40, 16], [40, 14], [36, 14], [36, 12], [40, 12] ] ,[ [38, 16], [38, 18], [28, 18], [28, 16], [32, 16] ] ,[ [34, 18], [34, 22], [40, 22], [40, 26], [36, 26], [36, 24], [34, 24] ] ,[ [32, 18], [32, 24] ] ,[ [34, 20], [40, 20], [40, 18] ] ,[ [40, 26], [42, 26] ] ,[ [36, 24], [38, 24] ] ]; // ,[ [, ], [, ], [, ], [, ], [, ], [, ] ] // Juste pour l'information de la hauteur du cylindre Paths04=[ [ [26, -1], [44, 29] ] // 29 == 28+1, un peu plus haut que le cylindre précédent. ]; // Définit le labyrinthe à utiliser aPaths = [Paths01, Paths02, Paths03, Paths04]; Paths = aPaths[nBoite-1]; // Grandeurs dépendantes des paramètres de base donné en début de fichier nbSeparationVerticales = Paths[0][0][0]; nbSeparationHorizontales = Paths[0][len(Paths[0])-1][1] - 2; // Position horizontale du trou final PosXTrouFinal = Paths[0][len(Paths[0])-1][0]; HCylindre = (nbSeparationHorizontales + 3.5) * Size; // Hauteur du cylindre // Epaisseur des cylindres EpaisseurCyl = RayonDifference - RayonDelta; // Rayon extérieur du cylindre en cours de traitement RayonCylExt = RayonCylExt01 + (nBoite-1) * RayonDifference; // Rayon du trou intérieur du cylindre en cours de traitement RayonCylInt = RayonCylExt - EpaisseurCyl; // Rayon de la base RayonBase = RayonCylExt + RayonDifference; // ####################### Librairie de construction du Labyrinthe #################### include nCas = 1; if (nCas == 1) { // Construction finale difference() { if (nBoite < nBoiteMax) { // Tous les cylindres, sauf le dernier union() { // Cylindre avec les chemins du labyrinthes difference() { translate([0,0,-HCylindre]) cylinder( h=HCylindre, r1=RayonCylExt, r2=RayonCylExt ,center=false, $fn=60); // $fn = nombre de faces Labyrinthe(); rotate([0,0,180]) Labyrinthe(); if (nBoite > 1) { // Adjonction de petites trous pour coincer le cylindre contenant celui en cours eps1 = 0.2; larg1 = 1.6; // == 2.2 - 0.6 == espace pour la partie qui coince les cylindres ensembles rotate([0,0,78]) rotate_extrude(angle=24, convexity = 10, $fn = 120) translate([RayonCylInt-eps1, -2.0-larg1, 0]) square([RayonDelta+eps1,larg1]); rotate([0,0,180+78]) rotate_extrude(angle=24, convexity = 10, $fn = 120) translate([RayonCylInt-eps1, -2.0-larg1, 0]) square([RayonDelta+eps1,larg1]); } } // difference if (nBoite < nBoiteMax-1) { // Base // La base est différente pour l'avant dernier cylindre difference() { union() { translate([0,0,-HCylindre - Htot_Base]) cylinder( h=Hchampfer_Base, r1=RayonBase - Hchampfer_Base , r2=RayonBase, center=false, $fn=60); translate([0,0,-HCylindre - (Htot_Base - Hchampfer_Base)]) cylinder( h=Htot_Base - Hchampfer_Base, r1=RayonBase , r2=RayonBase, center=false, $fn=60); } // union() // Encoches dans la base rotate([0,0, Paths[0][len(Paths[0])-1][0] * 180 / nbSeparationVerticales]) translate([RayonBase, 0, -HCylindre - Htot_Base-0.1]) myPolyVertical(10); rotate([0,0, 180 + Paths[0][len(Paths[0])-1][0] * 180 / nbSeparationVerticales]) translate([RayonBase, 0, -HCylindre - Htot_Base-0.1]) myPolyVertical(10); } // difference() de la Base } // if (nBoite < nBoiteMax-1) if (nBoite == nBoiteMax-1) { // Base différente pour l'avant-dernier cylindre R1 = RayonCylExt + 1.6; // Rayon de la base qui touche le plateau // Rayon de la base ayant des côtés verticaux R2 = RayonCylExt + (Htot_Base - 3*Hchampfer_Base); Scal = R2 / R1; // $fn=10 indique un polygone régulier à 10 côtés rotate([0,0, Paths[0][len(Paths[0])-1][0] * 180 / nbSeparationVerticales]) translate([0, 0, -HCylindre - Htot_Base]) linear_extrude( height=3*Hchampfer_Base, center=false, convexity=10, twist=0 ,scale=[Scal, Scal]) circle(r=R1, $fn=10); rotate([0,0, Paths[0][len(Paths[0])-1][0] * 180 / nbSeparationVerticales]) translate([0, 0, -HCylindre - (Htot_Base - 3*Hchampfer_Base)]) linear_extrude( height=(Htot_Base - 3*Hchampfer_Base), center=false, convexity=10) circle(r=R2, $fn=10); } // if (nBoite == nBoiteMax-1) } // union } // if (nBoite < nBoiteMax) { else { // Le dernier "cylindre", celui qui couvre le tout et qui n'a pas de labyrinthe difference() { union() { // Base // Rayon extérieur du cylindre précédent. RayonCylExt_Precedent = RayonCylExt01 + (nBoite-2) * (EpaisseurCyl + RayonDelta); R1 = RayonCylExt_Precedent + 1.6; // Rayon de la base qui touche le plateau // Rayon de la base ayant des côtés verticaux R2 = RayonCylExt_Precedent + (Htot_Base - 3*Hchampfer_Base); Scal = R2 / R1; // $fn=10 indique un polygone régulier à 10 côtés translate([0, 0, -HCylindre - Htot_Base]) linear_extrude( height=3*Hchampfer_Base ,center=false, convexity=10, twist=0 ,scale=[Scal, Scal]) circle(r=R1, $fn=10); translate([0, 0, -HCylindre - (Htot_Base - 3*Hchampfer_Base)]) linear_extrude( height=HCylindre + (Htot_Base - 3*Hchampfer_Base) ,center=false, convexity=10) circle(r=R2, $fn=10); // $fn = nombre de faces du cylindre } // union // Adjonction de petites trous pour coincer le cylindre contenant celui en cours eps1 = 0.2; larg1 = 1.6; // == 2.2 - 0.6 == espace pour la partie qui coince les cylindres ensembles rotate([0,0,78]) rotate_extrude(angle=24, convexity = 10, $fn = 120) translate([RayonCylInt-eps1, -2.0-larg1, 0]) square([RayonDelta+eps1,larg1]); rotate([0,0,180+78]) rotate_extrude(angle=24, convexity = 10, $fn = 120) translate([RayonCylInt-eps1, -2.0-larg1, 0]) square([RayonDelta+eps1,larg1]); } // difference() } // Trou dans le cylindre translate([0,0,-HCylindre - Htot_Base + BaseEpaisseur]) cylinder( h=HCylindre + Htot_Base ,r1=RayonCylInt ,r2=RayonCylInt ,center=false, $fn=60); } // difference if (nBoite < nBoiteMax) { // Adjonction de petites couches pour coincer le cylindre contenant celui en cours AngleCroche = 180 * PosXTrouFinal / nbSeparationVerticales + 90 - 20 / 2; eps2 = 0.2; rotate([0,0,AngleCroche]) rotate_extrude(angle=20, convexity = 10, $fn = 120) translate([RayonCylExt-eps2, -HCylindre+2.0, 0]) square([RayonDelta+0.1+eps2,1.2]); rotate([0,0,180+AngleCroche]) rotate_extrude(angle=20, convexity = 10, $fn = 120) translate([RayonCylExt-eps2, -HCylindre+2.0, 0]) square([RayonDelta+0.1+eps2,1.2]); } if (nBoite > 1) { // Les deux taitons qui suivent le labyrinthe. // Le labyrinthe intérieur n'a pas de taitons. unTaiton(0); unTaiton(nbSeparationVerticales); } } // if (nCas == 1) // Ce qui suit est pour faire des tests. else if (nCas == 2) { Labyrinthe(); } else if (nCas == 3) { difference() { translate([0,0,-HCylindre]) cylinder(h=HCylindre, r1=RayonCylExt, r2=RayonCylExt, center=false); Labyrinthe(); } } else if (nCas == 4) { translate([0,0,0]) myPolyHorizontal(7, 0); translate([RayonCylExt,0,-0.6]) myPolyVertical(3); rotate([0,0,7*180/nbSeparationVerticales]) translate([Rayon,0,-0.6]) myPolyVertical(2); translate([0,0,-HCylindre]) cylinder(h=HCylindre, r1=RayonCylExt, r2=RayonCylExt, center=false); }