/* Project : Kyrgyz Yurt Created by : Quentin BENETHUILLERE Date Of Creation : 2020/08/30 Last modification : 2021/02/28 */ // Definition of variables user can interact with : $fn = 100; // Accuracy of the model auto_support=0; // Determine whether the tunduk can be 3D printed without any support. 0 = support required (but more representative of reality), 1 = support not required (but less representative of reality). r_yurt_cylinder =45; // Radius (external) of the yurt cylinder r_tunduk_cylinder = 20; // Radius (external) of the yurt top (tunduk) r_tunduk_dome_shape_external = 2.5*r_tunduk_cylinder; // Radius of the sphere used for building the tunduk => controls the curve of the tunduk dome. Warning : Minimum = r_tunduk_cylinder h_yurt_base = 2; // Height of the yurt base h_door_top = 5; //Height of the horizontal top frame of the door h_posts = 5; // Height of the post supporting the tunduk h_tunduk_top = 5; // Height of the yurt top l_square = 6; // Length (internal) of the side squares (rhombus to be more accurate) w_door_posts = 5; // Width of the lateral door frames w_door = 40; // Door width (external) w_tunduk_spacing = 3 ; // Space between 2 tunduk frames (in the dome part) t_yurt = 3; // Thickness of the yurt t_tunduk = t_yurt; // Thickness tunduk a_diag_posts=25; // Angle for diagonal posts nb_squares = 3; // Number of rhumbus on each column m_diff = 10; // Margin to be used when doing differences of objects // Computed variables to facilitate coding : d_square = l_square*sqrt(2); // Diagonal (internal) of the side square nb_rotations=floor(2*3.141*r_yurt_cylinder/(d_square+t_yurt)); // Number of rotations to be performed to make the holes on the yurt side (as if the door was not there). h_displacement_diag_posts = t_yurt/2*sin(90-a_diag_posts); // Vertical displacement of the extremities of the diags posts due to the rotation. l_displacement_diag_posts = t_yurt/2*cos(90-a_diag_posts); // Horizontal displacement of the extremities of the diags posts due to the rotation. // Length of the diagonal posts (depending whether "auto_support" variable is set to 1 or not) // As a reminder for condition-based variables: "a=1; b=2; c= a==b ? 4 : 5 ;" l_diag_posts = auto_support==1 ? (r_yurt_cylinder-2*l_displacement_diag_posts-r_tunduk_cylinder+t_yurt)/cos(a_diag_posts) : (r_yurt_cylinder-r_tunduk_cylinder)/cos(a_diag_posts) ; h_diag_posts=l_diag_posts*sin(a_diag_posts); // Vertical projection measurement (height) of the diagonal posts. a_door = asin(w_door/(2*r_yurt_cylinder))*2; // angle covered by the yurt door door_back = r_yurt_cylinder*(1-cos(a_door/2)); h_yurt_cylinder = nb_squares*(t_yurt+l_square*sqrt(2)); // Height of the yurt cylinder h_cut_tunduk = r_tunduk_dome_shape_external*sin(acos(r_tunduk_cylinder/r_tunduk_dome_shape_external)); // Distance between the center of the dome sphere and where it nees to be cut horizontally alpha=acos(r_tunduk_cylinder/r_tunduk_dome_shape_external); // If the dome shape radius is equal to the radius of the tunduk cylinder, the adjustment is equal to the thickness of the yurt. r_tunduk_dome_shape_internal = r_tunduk_dome_shape_external==r_tunduk_cylinder ? t_yurt : r_tunduk_dome_shape_external-h_cut_tunduk/(sin(atan(h_cut_tunduk/(r_tunduk_cylinder-t_yurt)))); // Display variables : echo(nb_rotations=nb_rotations); echo(door_back=door_back); echo("test",r_tunduk_cylinder/r_tunduk_dome_shape_external*t_yurt); echo(alpha=alpha); echo(h_diag_posts=h_diag_posts); echo(r_tunduk_dome_shape_internal=r_tunduk_dome_shape_internal); // Basic Cylinder : module basic_cylinder(ext_radius,thickness,height,margin_diff){ difference(){ cylinder(r=ext_radius,h=height); translate([0,0,-margin_diff]){ cylinder(r=ext_radius-thickness,h=height+margin_diff*2); }; // End of translate }; // Enf of difference }; // End of module // Yurt Base : module yurt_base(){ basic_cylinder(r_yurt_cylinder,t_yurt,h_yurt_base,m_diff); }; // End of module // Module to be used for keeping only the circle part related to the door or on the opposite to get rid of the door part and keeping the rest of the yurt cylinder. module door_section(door_to_make_difference){ difference(){ if (door_to_make_difference==1){ // Note : In this "if" condition, the "m_diff" used as been divided by 2 compare to everywhere else in this code (it was necessary to avoid weird displays). translate([0,0,-m_diff/2]){ basic_cylinder(r_yurt_cylinder+m_diff,t_yurt+2*m_diff,h_yurt_cylinder+m_diff,m_diff); }; // Enf of translate } else { basic_cylinder(r_yurt_cylinder,t_yurt,h_yurt_cylinder,m_diff); } rotate([0,0,a_door/2]){ translate([0,0,-m_diff]){ cube([r_yurt_cylinder+m_diff,r_yurt_cylinder+m_diff,h_yurt_cylinder+2*m_diff]); }; // Enf of translate }; // End of rotate rotate([0,0,270-a_door/2]){ translate([0,0,-m_diff]){ cube([r_yurt_cylinder+m_diff,r_yurt_cylinder+m_diff,h_yurt_cylinder+2*m_diff]); }; // Enf of translate }; // End of rotate translate([-(r_yurt_cylinder+m_diff)/2,0,h_yurt_cylinder/2]){ cube([r_yurt_cylinder+m_diff,2*(r_yurt_cylinder+m_diff),h_yurt_cylinder+2*m_diff],center=true); }; // Enf of translate }; // Enf of difference }; // End of module // Yurt Door : module yurt_door(){ difference(){ door_section(0); translate([0,0,h_yurt_cylinder/2-h_door_top]){ cube([2*r_yurt_cylinder+2*m_diff,w_door-2*w_door_posts,h_yurt_cylinder],center=true); }; // End of translate }; // End of difference }; // End of module // Cylinder of the yurt : module yurt_cylinder_frame(){ difference(){ basic_cylinder(r_yurt_cylinder,t_yurt,h_yurt_cylinder,m_diff); for(i=[0:nb_squares]){ for(j=[0:nb_rotations-1]){ translate([0,0,i*(sqrt(2)*l_square+t_yurt)]){ rotate([45,0,j*360/(nb_rotations)]){ rotate([0,90,0]){ translate([0,0,r_yurt_cylinder/2]){ cube([l_square,l_square,r_yurt_cylinder+m_diff],center=true); }; // End of translate }; // End of rotate }; // Enf of rotate }; // End of translate }; // End of for "j" }; // Enf of for "i" for(i=[0:nb_squares]){ for(j=[0:nb_rotations-1]){ translate([0,0,(i+0.5)*(sqrt(2)*l_square+t_yurt)]){ rotate([45,0,(j+0.5)*360/(nb_rotations)]){ rotate([0,90,0]){ translate([0,0,r_yurt_cylinder/2]){ cube([l_square,l_square,r_yurt_cylinder],center=true); }; // End of translate }; // Enf of rotate }; // End of rotate }; // End of translate }; // End of for "j" }; // End of for "i" door_section(1); }; // End of difference } // End of module // Posts : module yurt_posts(){ for(j=[0:nb_rotations-1]){ rotate([0,0,(j+0.5)*360/(nb_rotations)]){ // Important Note : the first square considered is along the x axis. // Vertical posts translate([r_yurt_cylinder-t_yurt/2,0,h_yurt_cylinder+h_yurt_base+h_posts/2]){ cube([t_yurt,t_yurt,h_posts],center=true); }; // Diagonal posts translate([r_yurt_cylinder-l_displacement_diag_posts,0,h_yurt_base+h_yurt_cylinder+h_posts-h_displacement_diag_posts]){ rotate([0,-(90-a_diag_posts),0]){ translate([-t_yurt/2,-t_yurt/2,0]){ // Translation needed because those diagonal posts are not centered unlike the vertical posts. cube([t_yurt,t_yurt,l_diag_posts]); }; // End of translate }; // End of rotate }; // End of translate }; // Enf of rotate }; // End of for "j" }; // End of module // Cylindre of the tunduk (top of the yurt) : module tunduk_cylindre(){ basic_cylinder(r_tunduk_cylinder,t_yurt,h_tunduk_top,m_diff); }; // End of module module tunduk_dome(){ difference(){ // Note : it has been dediced to specify the number of faces in this particular module to avoid seeing little gaps on the tunduk due to an inappropriate accuracy of the model. sphere(r=r_tunduk_dome_shape_external,$fn=150); sphere(r=r_tunduk_dome_shape_external-r_tunduk_dome_shape_internal,$fn=150); translate([0,0,-(r_tunduk_dome_shape_external-h_cut_tunduk)]){ cube([2*r_tunduk_dome_shape_external,2*r_tunduk_dome_shape_external,2*r_tunduk_dome_shape_external],center=true); }; // End of translate }; // End of difference }; // End of module module cut_tunduk_assembly_one_direction(){ union(){ // Center parts translate([0,(t_tunduk+w_tunduk_spacing)/2,0]){ cube([2*(r_tunduk_dome_shape_external+m_diff),w_tunduk_spacing,2*(r_tunduk_dome_shape_external+m_diff)],center=true); }; // End of translate translate([0,-(t_tunduk+w_tunduk_spacing)/2,0]){ cube([2*r_tunduk_dome_shape_external,w_tunduk_spacing,2*(r_tunduk_dome_shape_external+m_diff)],center=true); }; // End of translate // External parts translate([0,t_tunduk*3/2+2*w_tunduk_spacing/2+r_tunduk_dome_shape_external/2,0]){ cube([2*r_tunduk_dome_shape_external,r_tunduk_dome_shape_external,2*(r_tunduk_dome_shape_external+m_diff)],center=true); }; // End of translate translate([0,-(t_tunduk*3/2+2*w_tunduk_spacing/2+r_tunduk_dome_shape_external/2),0]){ cube([2*r_tunduk_dome_shape_external,r_tunduk_dome_shape_external,2*(r_tunduk_dome_shape_external+m_diff)],center=true); }; // End of translate }; // End of union }; // End of module module cut_tunduk_assembly_both_directions(){ union(){ cut_tunduk_assembly_one_direction(); rotate([0,0,90]){ cut_tunduk_assembly_one_direction(); }; // End of rotate }; // End of union }; module tunduk_final(){ union(){ difference(){ tunduk_dome(); translate([0,0,r_tunduk_dome_shape_external/2+m_diff]){ cut_tunduk_assembly_one_direction(); }; // End of translate }; // End of difference difference(){ tunduk_dome(); translate([0,0,r_tunduk_dome_shape_external/2+m_diff]){ rotate([0,0,90]){ cut_tunduk_assembly_one_direction(); }; // End of rotate }; // End of translate }; // End of difference }; // End of union }; union(){ yurt_base(); translate([0,0,h_yurt_base]){ yurt_door(); yurt_cylinder_frame(); }; yurt_posts(); if (auto_support==1){ translate([0,0,h_yurt_base+h_yurt_cylinder+h_posts+h_diag_posts-2*h_displacement_diag_posts]){ tunduk_cylindre(); }; translate([0,0,h_yurt_base+h_yurt_cylinder+h_posts+h_diag_posts-2*h_displacement_diag_posts+h_tunduk_top-h_cut_tunduk]){ tunduk_final(); }; } else { translate([0,0,h_yurt_base+h_yurt_cylinder+h_posts+h_diag_posts-h_tunduk_top/2-t_yurt/(2*cos(a_diag_posts))]){ tunduk_cylindre(); }; translate([0,0,h_yurt_base+h_yurt_cylinder+h_posts+h_diag_posts+h_tunduk_top/2-t_yurt/(2*cos(a_diag_posts))-h_cut_tunduk]){ tunduk_final(); }; } }; // End of union