/*
    This file is part of SBC Case Builder https://github.com/hominoids/SBC_Case_Builder
    Copyright 2022,2023,2024 Edward A. Kisiel hominoid@cablemi.com

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>
    Code released under GPLv3: http://www.gnu.org/licenses/gpl.html


           NAME: case_bottom
    DESCRIPTION: creates case bottom for supported designs
           TODO: none

          USAGE: case_bottom(case_design)

*/

module case_bottom(case_design) {

    lip = 5;
    vu_rotation = [15,0,0];
    case_fn = 360;     // circle segments for round cases
    case_ffn = 90;     // circle segments for fillet of round cases

    difference() {
        union() {
            difference() {
                union() {
                    if(case_design == "shell") {
                        difference() {
                            translate([(width/2)-wallthick-gap,(depth/2)-wallthick-gap,bottom_height/2]) 
                                cube_fillet_inside([width,depth,bottom_height], 
                                    vertical=[corner_fillet,corner_fillet,corner_fillet,corner_fillet], 
                                        top=[0,0,0,0], bottom=[edge_fillet,edge_fillet,edge_fillet,edge_fillet,edge_fillet], $fn=90);
                            translate([(width/2)-wallthick-gap,
                                (depth/2)-wallthick-gap,(bottom_height/2)+floorthick]) 
                                    cube_fillet_inside([width-(wallthick*2),depth-(wallthick*2),bottom_height], 
                                        vertical=[corner_fillet-1,corner_fillet-1,corner_fillet-1,corner_fillet-1],
                                            top=[0,0,0,0], bottom=[edge_fillet,edge_fillet,edge_fillet,edge_fillet,edge_fillet], $fn=90);
                        }
                    }
                    if(case_design == "panel") {
                       union() {
                           translate([-gap,-gap,0]) 
                                cube([width-(2*wallthick),depth-(2*wallthick),floorthick]);
                            translate([(width*(1/5))-8-(wallthick+gap),depth-(2*wallthick)-gap-adj,0]) 
                                    cube([8,wallthick+2*adj,floorthick]);
                            translate([width-(width*(1/5))-(wallthick+gap),depth-(2*wallthick)-gap-adj,0])
                                    cube([8,wallthick+2*adj,floorthick]);
                            translate([(width*(1/5))-8-(wallthick+gap),-wallthick-gap+adj,0])
                                    cube([8,wallthick+2*adj,floorthick]);
                            translate([width-(width*(1/5))-(wallthick+gap),-wallthick-gap+adj,0])
                                    cube([8,wallthick+2*adj,floorthick]);
                        }
                    }
                    if(case_design == "stacked") {
                        translate([(width/2)-wallthick-gap,(depth/2)-wallthick-gap,floorthick/2]) 
                            cube_fillet_inside([width-(2*wallthick),depth-(2*wallthick),floorthick], 
                                vertical=[corner_fillet,corner_fillet,corner_fillet,corner_fillet], 
                                    top=[0,0,0,0], bottom=[0,0,0,0], $fn=90);
                    }
                    if(case_design == "tray") {
                        difference() {
                            translate([(width/2)-wallthick-gap,(depth/2)-wallthick-gap,(bottom_height)/2]) 
                                cube_fillet_inside([width,depth,bottom_height], 
                                    vertical=[0,0,0,0], top=[0,0,0,0], 
                                        bottom=[edge_fillet,edge_fillet,edge_fillet,edge_fillet,edge_fillet], $fn=90);
                            translate([(width/2)-wallthick-gap,(depth/2)-wallthick-gap,(bottom_height/2)+floorthick]) 
                                cube_fillet_inside([width-(wallthick*2),depth-(wallthick*2),bottom_height+adj], 
                                    vertical=[corner_fillet-1,corner_fillet-1,corner_fillet-1,corner_fillet-1],
                                        top=[0,0,0,0],bottom=[2,2,2,2], $fn=90);
                        }
                        // right side nut
                        translate([width-wallthick-gap-wallthick-4+adj,wallthick+gap+10,
                                floorthick+3.4]) rotate([90,0,90]) 
                                    cylinder(d=10, h=4, $fn=6);
                        // left side nut
                        translate([-adj-gap,wallthick+gap+10,floorthick+3.4]) 
                            rotate([90,0,90]) cylinder(d=10, h=4, $fn=6);
                        if(depth >= 75 && sbc_model != "visionfive2" && sbc_model != "visionfive2q" && 
                            sbc_model != "rock5b" && sbc_model != "rock5bq" && sbc_model != "rock5b-v1.3") {
                            translate([width-wallthick-gap-wallthick-4+adj,depth-wallthick-gap-10,
                                    floorthick+3.4]) rotate([90,0,90]) cylinder(d=10, h=4, $fn=6);
                            translate([-adj-gap,depth-wallthick-gap-10,floorthick+3.4]) 
                                rotate([90,0,90]) cylinder(d=10, h=4, $fn=6);
                        }
                        else {
                            if(sbc_model == "visionfive2" || sbc_model == "visionfive2q" || sbc_model == "rock5b" ||  
                                sbc_model == "rock5bq" || sbc_model == "rock5b-v1.3") {
                                translate([width-wallthick-gap-wallthick-4+adj,wallthick+gap+58,
                                        floorthick+3.4]) rotate([90,0,90]) cylinder(d=10, h=4, $fn=6);
                                translate([-adj-gap,wallthick+gap+58,floorthick+3.4]) 
                                    rotate([90,0,90]) cylinder(d=10, h=4, $fn=6);
                            }
                            else {
                                translate([width-wallthick-gap-wallthick-4+adj,wallthick+gap+40,
                                        floorthick+3.4]) rotate([90,0,90]) cylinder(d=10, h=4, $fn=6);
                                translate([-adj-gap,wallthick+gap+40,floorthick+3.4]) 
                                    rotate([90,0,90]) cylinder(d=10, h=4, $fn=6);
                            }
                        }
                        
                        // front panel
                        if(case_style == "sides" || case_style == "vu5" || case_style == "vu7") {
                            translate([-wallthick-gap,depth-(2*wallthick)-gap,bottom_height-adj]) 
                                rotate([0,0,0]) cube([width,wallthick,top_height]);
                        }
                        else {
                            translate([-wallthick-gap,depth-(2*wallthick)-gap,bottom_height-adj]) 
                                rotate([0,0,0]) cube([width,wallthick,top_height-floorthick]);
                        }
                        
                        // rear panel
                        translate([-wallthick-gap,-wallthick-gap,bottom_height-adj]) 
                            cube([width,wallthick,top_height-floorthick]);
                        
                    }
                    if(case_design == "round") {
                        difference() {
                            translate([pcb_width/2,pcb_depth/2,bottom_height/2]) rotate([0,0,30]) 
                                cylinder_fillet_inside(h=bottom_height, r=case_diameter/2, 
                                    top=0, bottom=edge_fillet, $fn=case_fn, fillet_fn=case_ffn, center=true);
                            translate([pcb_width/2,pcb_depth/2,(bottom_height/2)+floorthick]) rotate([0,0,30]) 
                                cylinder_fillet_inside(h=bottom_height+adj, r=(case_diameter/2)-lip/2, 
                                    top=0, bottom=edge_fillet-1, $fn=case_fn, fillet_fn=case_ffn, center=true);
                            difference() {
                                translate([pcb_width/2,pcb_depth/2,bottom_height-lip]) rotate([0,0,30]) 
                                    cylinder(h=lip+adj, r=(case_diameter/2)+1, $fn=case_fn);
                                translate([pcb_width/2,pcb_depth/2,bottom_height-lip]) rotate([0,0,30]) 
                                    cylinder(h=lip+2*adj, r=(case_diameter/2)-lip/4, $fn=case_fn);
                            }
                        }
                        difference() {
                            translate([pcb_width/2,pcb_depth/2,(bottom_height/2)+2*floorthick]) rotate([0,0,30]) 
                                cylinder_fillet_inside(h=bottom_height+adj+floorthick+lip,
                                    r=(case_diameter/2)-lip/2,top=0,bottom=edge_fillet-1, $fn=case_fn, 
                                        fillet_fn=case_ffn, center=true);
                            if(width/depth >= 1.4 && sbc_model != "vim1" && sbc_model != "vim2" && 
                               sbc_model != "vim3l" && sbc_model != "vim3" && sbc_model != "vim4" && 
                                    sbc_model != "rpizero" && sbc_model != "rpizero2w") {
                                translate([-16,(depth/2)-150,-adj])
                                    cube([width+10,300,case_z-2*floorthick-2]); 
                                translate([width-9,(depth/2)-62.5,bottom_height-2*adj])
                                    cube([20,110,top_height-2*floorthick-2]);
                            }
                            else {
                                translate([-width/2,0,-adj])
                                    cube([300,depth+100,case_z-2*floorthick-2]); 
                                translate([(-width+50)/2,-50,bottom_height-2*adj])
                                    cube([width+50,50+adj,top_height-2*floorthick-2]);
                            }
                        }
                    }
                    if(case_design == "hex") {
                        if(width/depth >= 1.4 && sbc_model != "vim1" && sbc_model != "vim2" && 
                            sbc_model != "vim3l" && sbc_model != "vim3" && sbc_model != "vim4" && 
                                sbc_model != "rpizero" && sbc_model != "rpizero2w") {
                            difference() {
                                translate([pcb_width/2,pcb_depth/2,bottom_height/2]) rotate([0,0,30]) 
                                    cylinder_fillet_inside(h=bottom_height, r=case_diameter/2, 
                                        top=0, bottom=edge_fillet, $fn=6, fillet_fn=case_ffn, center=true);
                                translate([pcb_width/2,pcb_depth/2,(bottom_height/2)+floorthick]) rotate([0,0,30]) 
                                    cylinder_fillet_inside(h=bottom_height+adj,r=(case_diameter/2)-lip/2,top=0, 
                                        bottom=edge_fillet-1,$fn=6,fillet_fn=case_ffn, center=true);
                                difference() {
                                    translate([pcb_width/2,pcb_depth/2,bottom_height-lip]) rotate([0,0,30]) 
                                        cylinder(h=lip+adj,r=(case_diameter/2)+1, $fn=6);
                                    translate([pcb_width/2,pcb_depth/2,bottom_height-lip]) rotate([0,0,30]) 
                                        cylinder(h=lip+2*adj,r=(case_diameter/2)-lip/4, $fn=6);
                                }
                            }
                            difference() {
                                translate([pcb_width/2,pcb_depth/2,(bottom_height/2)+2*floorthick]) rotate([0,0,30]) 
                                    cylinder_fillet_inside(h=bottom_height+adj+floorthick+lip,
                                        r=(case_diameter/2)-lip/2,top=0, bottom=edge_fillet-1, $fn=6, 
                                            fillet_fn=case_ffn, center=true);
                                translate([-16,(depth/2)-150,-adj])
                                    cube([width+10,300,case_z-2*floorthick-2]); 
                                translate([width-9,(depth/2)-62.5,bottom_height-2*adj])
                                    cube([20,110,top_height-2*floorthick-2]); 
                            }
                        }
                        else {
                            difference() {
                                translate([pcb_width/2,pcb_depth/2,bottom_height/2]) rotate([0,0,0]) 
                                    cylinder_fillet_inside(h=bottom_height, r=hex_diameter/2, 
                                        top=0, bottom=edge_fillet, $fn=6, fillet_fn=case_ffn, center=true);
                                translate([pcb_width/2,pcb_depth/2,(bottom_height/2)+floorthick]) rotate([0,0,0]) 
                                    cylinder_fillet_inside(h=bottom_height+adj,r=(hex_diameter/2)-lip/2,top=0, 
                                        bottom=edge_fillet-1,$fn=6,fillet_fn=case_ffn, center=true);
                                difference() {
                                    translate([pcb_width/2,pcb_depth/2,bottom_height-lip]) rotate([0,0,0]) 
                                        cylinder(h=lip+adj,r=(hex_diameter/2)+1, $fn=6);
                                    translate([pcb_width/2,pcb_depth/2,bottom_height-lip]) rotate([0,0,0]) 
                                        cylinder(h=lip+2*adj,r=(hex_diameter/2)-lip/4, $fn=6);
                                }
                            }
                            difference() {
                                translate([pcb_width/2,pcb_depth/2,(bottom_height/2)+2*floorthick]) rotate([0,0,0]) 
                                    cylinder_fillet_inside(h=bottom_height+adj+floorthick+lip,
                                        r=(hex_diameter/2)-lip/2,top=0, bottom=edge_fillet-1, $fn=6, 
                                            fillet_fn=case_ffn, center=true);
                                translate([-width/2,0,-adj])
                                    cube([300,depth+100,case_z-2*floorthick-2]); 
                                translate([(-width+50)/2,-50,bottom_height-2*adj])
                                    cube([width+50,50+adj,top_height-2*floorthick-2]);
                            }
                        }
                    }
                    if(case_design == "snap") {
                        difference() {
                            translate([(width/2)-wallthick-gap,(depth/2)-wallthick-gap,(floorthick+case_z)/2]) 
                                cube_fillet_inside([width,depth,floorthick+case_z], 
                                    vertical=[corner_fillet,corner_fillet,corner_fillet,corner_fillet], 
                                        top=[0,0,0,0], bottom=[edge_fillet,edge_fillet,edge_fillet,edge_fillet,edge_fillet], $fn=90);
                            translate([(width/2)-wallthick-gap,(depth/2)-wallthick-gap,floorthick+(floorthick+case_z)/2]) 
                                cube_fillet_inside([width-(wallthick*2),depth-(wallthick*2),case_z+floorthick], 
                                        vertical=[corner_fillet-1,corner_fillet-1,corner_fillet-1,corner_fillet-1],
                                            top=[0,0,0,0], bottom=[edge_fillet,edge_fillet,edge_fillet,edge_fillet,edge_fillet], $fn=90);
                            // snap top indent
                            translate([-gap-wallthick+.75,(depth/2)-(depth*.75)/2-gap-wallthick,case_z-.5]) 
                                rotate([0,45,0]) cube([4,depth*.75,4]);
                            translate([width-wallthick-gap-6.25,(depth/2)-(depth*.75)/2-gap-wallthick,case_z-.5])
                                rotate([0,45,0]) cube([4,depth*.75,4]);
                        }
                    }
                    if(case_design == "fitted") {
                        difference() {
                            translate([(width/2)-wallthick-gap,(depth/2)-wallthick-gap,case_z/2]) 
                                cube_fillet_inside([width,depth,case_z], 
                                    vertical=[corner_fillet,corner_fillet,corner_fillet,corner_fillet], 
                                        top=[0,0,0,0], bottom=[edge_fillet,edge_fillet,edge_fillet,edge_fillet,edge_fillet], $fn=90);
                            translate([(width/2)-wallthick-gap,
                                (depth/2)-wallthick-gap,(case_z/2)+floorthick]) 
                                    cube_fillet_inside([width-(wallthick*2),depth-(wallthick*2),case_z], 
                                        vertical=[corner_fillet-1,corner_fillet-1,corner_fillet-1,corner_fillet-1],
                                            top=[0,0,0,0], bottom=[edge_fillet,edge_fillet,edge_fillet,edge_fillet,edge_fillet], $fn=90);
                            difference() {
                                translate([(width/2)-wallthick-gap,(depth/2)-wallthick-gap,case_z-lip/2]) 
                                    cube_fillet_inside([width+adj,depth+adj,lip+adj], 
                                        vertical=[corner_fillet,corner_fillet,corner_fillet,corner_fillet], 
                                            top=[0,0,0,0],bottom=[edge_fillet,edge_fillet,edge_fillet,edge_fillet,edge_fillet], $fn=90);
                                
                                translate([(width/2)-wallthick-gap,(depth/2)-wallthick-gap,case_z-lip/2]) 
                                    cube_fillet_inside([width-wallthick,depth-wallthick,lip+adj], 
                                        vertical=[corner_fillet-1,corner_fillet-1,corner_fillet-1,corner_fillet-1],top=[0,0,0,0],
                                            bottom=[edge_fillet,edge_fillet,edge_fillet,edge_fillet,edge_fillet], $fn=90);
                            }
                        }
                    }
                    // additive accessories
                    if(accessory_name != "none") {
                        for (i=[1:11:len(accessory_data[a[0]])-1]) {
                            class = accessory_data[a[0]][i];
                            type = accessory_data[a[0]][i+1];
                            loc_x = accessory_data[a[0]][i+2];
                            loc_y = accessory_data[a[0]][i+3];
                            loc_z = accessory_data[a[0]][i+4];
                            face = accessory_data[a[0]][i+5];
                            rotation = accessory_data[a[0]][i+6];
                            parametric = accessory_data[a[0]][i+7];
                            size = accessory_data[a[0]][i+8];
                            data = accessory_data[a[0]][i+9];
                            mask = accessory_data[a[0]][i+10];

                            if(class == "add1" && face == "bottom") {
                                parametric_move_add(type, loc_x, loc_y, loc_z, face, rotation, parametric, size, data, mask);
                            }
                        }
                    }
                }
                // side attachment holes
                if(case_design == "tray") {
                    // right side bottom attachment holes
                    translate([width-2*(wallthick+gap)-sidethick-adj,wallthick+gap+10,
                        floorthick+3.4]) rotate([0,90,0]) cylinder(d=3, h=10+sidethick+(2*adj));
                    // right side bottom nut inset
                    translate([width-3.5-(2*wallthick)-gap-.6,wallthick+gap+10,
                        floorthick+3.4]) rotate([90,0,90]) cylinder(d=6.6, h=3.5, $fn=6);
                    // left side bottom attachment holes
                    translate([-wallthick-gap-adj,wallthick+gap+10,floorthick+3.4]) rotate([0,90,0]) 
                            cylinder(d=3, h=10+sidethick+(2*adj));
                    // left side bottom nut inset
                    translate([-gap+.6,wallthick+gap+10,floorthick+3.4]) 
                        rotate([90,0,90]) cylinder(d=6.6, h=3.5, $fn=6);
                    if(depth >= 75 && sbc_model != "visionfive2" && sbc_model != "visionfive2q" && 
                        sbc_model != "rock5b" && sbc_model != "rock5bq" && sbc_model != "rock5b-v1.3") {
                        translate([width-2*(wallthick+gap)-sidethick-adj,depth-wallthick-gap-10,
                            floorthick+3.4]) rotate([0,90,0]) 
                                cylinder(d=3, h=10+sidethick+(2*adj));
                        translate([-wallthick-gap-adj-6,depth-wallthick-gap-10,
                            floorthick+3.4]) rotate([0,90,0]) 
                                cylinder(d=3, h=10+sidethick+(2*adj));
                        translate([width-3.5-(2*wallthick)-gap-.6,depth-wallthick-gap-10,
                            floorthick+3.4])rotate([90,0,90]) cylinder(d=6.6, h=3.5, $fn=6);
                        translate([-gap+.6,depth-wallthick-gap-10,floorthick+3.4]) 
                            rotate([90,0,90]) cylinder(d=6.6, h=3.5, $fn=6);
                    }
                    else {
                        if(sbc_model == "visionfive2" || sbc_model == "visionfive2q" || sbc_model == "rock5b" ||  
                            sbc_model == "rock5bq" || sbc_model == "rock5b-v1.3") {
                            translate([width-3*(wallthick+gap)-adj,wallthick+gap+58,
                                floorthick+3.4]) rotate([0,90,0]) 
                                    cylinder(d=3, h=10+sidethick+(2*adj));
                            translate([-wallthick-gap-adj-6,wallthick+gap+58,
                                floorthick+3.4]) rotate([0,90,0]) 
                                    cylinder(d=3, h=10+sidethick+(2*adj));
                            translate([width-3.5-(2*wallthick)-gap-.6,wallthick+gap+58,
                                floorthick+3.4])rotate([90,0,90]) cylinder(d=6.6, h=3.5, $fn=6);
                            translate([-gap+.6,wallthick+gap+58,floorthick+3.4]) 
                                rotate([90,0,90]) cylinder(d=6.6, h=3.5, $fn=6);
                        }
                        else {
                            translate([width-3*(wallthick+gap)-adj,wallthick+gap+40,
                                floorthick+3.4]) rotate([0,90,0]) cylinder(d=3, h=10+sidethick+(2*adj));
                            translate([-wallthick-gap-adj-6,wallthick+gap+40,
                                floorthick+3.4]) rotate([0,90,0]) cylinder(d=3, h=10+sidethick+(2*adj));
                            translate([width-3.5-(2*wallthick)-gap-.6,wallthick+gap+40,
                                floorthick+3.4])rotate([90,0,90]) cylinder(d=6.6, h=3.5, $fn=6);
                            translate([-gap+.6,wallthick+gap+40,floorthick+3.4]) 
                                rotate([90,0,90]) cylinder(d=6.6, h=3.5, $fn=6);
                        }
                    }
                }
                // pcb standoff holes
                if(sbc_bottom_standoffs == true) {
                    for (i=[1:11:len(sbc_data[s[0]])-2]) {
                        class = sbc_data[s[0]][i+1];
                        type = sbc_data[s[0]][i+2];
                        id = sbc_data[s[0]][i+3];
                        pcbhole_x = sbc_data[s[0]][i+4]+pcb_loc_x;
                        pcbhole_y = sbc_data[s[0]][i+5]+pcb_loc_y;
                        pcbhole_z = sbc_data[s[0]][i+6];
                        pcbhole_size = sbc_data[s[0]][i+9][0];
                        pcbhole_pos = sbc_data[s[0]][i+10][4];

                        if (class == "pcbhole" && id == pcb_id && pcbhole_pos == "left_rear" && 
                            bottom_rear_left_enable == true && bottom_standoff[5] != "blind") {
                                translate([pcbhole_x,pcbhole_y,-1]) cylinder(d=6.5, h=bottom_height);
                        }
                        if (class == "pcbhole" && id == pcb_id && pcbhole_pos == "left_front" && 
                            bottom_front_left_enable == true && bottom_standoff[5] != "blind") {
                                translate([pcbhole_x,pcbhole_y,-1]) cylinder(d=6.5, h=bottom_height);
                        }
                        if (class == "pcbhole" && id == pcb_id && pcbhole_pos == "right_rear" && 
                            bottom_rear_right_enable == true && bottom_standoff[5] != "blind") {
                                translate([pcbhole_x,pcbhole_y,-1]) cylinder(d=6.5, h=bottom_height);
                        }
                        if (class == "pcbhole" && id == pcb_id && pcbhole_pos == "right_front" && 
                            bottom_front_right_enable == true && bottom_standoff[5] != "blind") {
                                translate([pcbhole_x,pcbhole_y,-1]) cylinder(d=6.5, h=bottom_height);
                        }

                    }
                }
                // extended standoff holes
                if(ext_bottom_standoffs == true) {
                    // right-rear standoff
                    if(((width-pcb_loc_x-pcb_width-(gap+2*wallthick) >= 10 || pcb_loc_y >= 10)) && 
                            ext_bottom_rear_right_enable == true && ext_bottom_standoff[5] != "blind") {
                        translate([width-ext_bottom_standoff_support_size/4-(2*(wallthick+gap))-(corner_fillet/2),
                            (corner_fillet/2)+ext_bottom_standoff_support_size/4,-1]) cylinder(d=6.5, h=bottom_height);
                    }
                    // right-front standoff
                    if(((width-pcb_loc_x-pcb_width-(gap+2*wallthick) >= 10 && depth-pcb_loc_y-pcb_depth >= 10) || 
                        (width-pcb_loc_x-pcb_width-(gap+2*wallthick) >= 10 && depth-pcb_loc_y-pcb_depth <= 10) ||
                            (width-pcb_loc_x-pcb_width-(gap+2*wallthick) <= 10 && depth-pcb_loc_y-pcb_depth >= 10)) &&
                                ext_bottom_front_right_enable == true && ext_bottom_standoff[5] != "blind") {
                        translate([width-ext_bottom_standoff_support_size/4-(corner_fillet/2)-(2*(wallthick+gap)),
                            depth-ext_bottom_standoff_support_size/4-(corner_fillet/2)-(2*(wallthick+gap)),-1]) 
                                cylinder(d=6.5, h=bottom_height);
                    }
                    // left-rear standoff
                    if((pcb_loc_x >= 10 || pcb_loc_y >= 10) && ext_bottom_rear_left_enable == true && ext_bottom_standoff[5] != "blind") {
                        translate([(corner_fillet/2)+ext_bottom_standoff_support_size/4,
                            (corner_fillet/2)+ext_bottom_standoff_support_size/4,-1]) cylinder(d=6.5, h=bottom_height);
                    }
                    // left-front standoff
                    if(((pcb_loc_x >= 10 && (depth-(pcb_loc_y+pcb_depth)) >= 10) || 
                        (pcb_loc_x <= 10 && (depth-(pcb_loc_y+pcb_depth)) >= 10) || 
                            (pcb_loc_x >= 10 && (depth-(pcb_loc_y+pcb_depth)) <= 10)) &&
                                ext_bottom_front_left_enable == true && ext_bottom_standoff[5] != "blind") {
                        translate([(corner_fillet/2)+ext_bottom_standoff_support_size/4,
                            depth-ext_bottom_standoff_support_size/4-(corner_fillet/2)-(2*(wallthick+gap)),-1]) 
                                cylinder(d=6.5, h=bottom_height);
                    }
                }
                // bottom cover pattern
                if(bottom_cover_pattern != "solid") {
                    if(bottom_cover_pattern == "hex_5mm") {
                        translate([1,0,-2]) vent_hex((width)/3.75,(depth)/6,floorthick+4,5,1.5,"horizontal");
                    }
                    if(bottom_cover_pattern == "hex_8mm") {
                        translate([1,2,-2]) vent_hex((width)/5.5,(depth)/9.5,floorthick+4,8,1.5,"horizontal");
                    }
                }
            }
            // pcb standoffs
            if(sbc_bottom_standoffs  == true) {
                    for (i=[1:11:len(sbc_data[s[0]])-2]) {
                        class = sbc_data[s[0]][i+1];
                        type = sbc_data[s[0]][i+2];
                        id = sbc_data[s[0]][i+3];
                        pcbhole_x = sbc_data[s[0]][i+4]+pcb_loc_x;
                        pcbhole_y = sbc_data[s[0]][i+5]+pcb_loc_y;
                        pcbhole_z = sbc_data[s[0]][i+6];
                        pcbhole_size = sbc_data[s[0]][i+9][0];
                        pcbhole_pos = sbc_data[s[0]][i+10][4];

                    if(class == "pcbhole" && id == pcb_id && 
                        (pcbhole_pos == "left_rear" || pcbhole_pos == "left_front" || pcbhole_pos == "right_rear" || pcbhole_pos == "right_front")) {
                        if (pcbhole_pos == "left_rear" && bottom_rear_left_enable == true) {
                            normal_standoff = [bottom_standoff[0],
                                                bottom_height-pcb_z+pcb_loc_z+bottom_rear_left_adjust,
                                                bottom_standoff[2],
                                                bottom_standoff[3],
                                                bottom_standoff[4],
                                                bottom_standoff[5],
                                                bottom_standoff[6],
                                                bottom_rear_left_support,
                                                bottom_standoff[8],
                                                bottom_standoff[9],
                                                bottom_standoff[10],
                                                bottom_standoff[11]];
                            translate([pcbhole_x,pcbhole_y,0]) standoff(normal_standoff);
                        }
                        if (pcbhole_pos == "left_front" && bottom_front_left_enable == true) {
                            normal_standoff = [bottom_standoff[0],
                                                bottom_height-pcb_z+pcb_loc_z+bottom_front_left_adjust,
                                                bottom_standoff[2],
                                                bottom_standoff[3],
                                                bottom_standoff[4],
                                                bottom_standoff[5],
                                                bottom_standoff[6],
                                                bottom_front_left_support,
                                                bottom_standoff[8],
                                                bottom_standoff[9],
                                                bottom_standoff[10],
                                                bottom_standoff[11]];
                            translate([pcbhole_x,pcbhole_y,0]) standoff(normal_standoff);
                        }
                        if (pcbhole_pos == "right_rear" && bottom_rear_right_enable == true) {
                            normal_standoff = [bottom_standoff[0],
                                                bottom_height-pcb_z+pcb_loc_z+bottom_rear_right_adjust,
                                                bottom_standoff[2],
                                                bottom_standoff[3],
                                                bottom_standoff[4],
                                                bottom_standoff[5],
                                                bottom_standoff[6],
                                                bottom_rear_right_support,
                                                bottom_standoff[8],
                                                bottom_standoff[9],
                                                bottom_standoff[10],
                                                bottom_standoff[11]];
                            translate([pcbhole_x,pcbhole_y,0]) standoff(normal_standoff);
                        }
                        if (pcbhole_pos == "right_front" && bottom_front_right_enable == true) {
                            normal_standoff = [bottom_standoff[0],
                                                bottom_height-pcb_z+pcb_loc_z+bottom_front_right_adjust,
                                                bottom_standoff[2],
                                                bottom_standoff[3],
                                                bottom_standoff[4],
                                                bottom_standoff[5],
                                                bottom_standoff[6],
                                                bottom_front_right_support,
                                                bottom_standoff[8],
                                                bottom_standoff[9],
                                                bottom_standoff[10],
                                                bottom_standoff[11]];
                            translate([pcbhole_x,pcbhole_y,0]) standoff(normal_standoff);
                        }
                    }
                }
            }

            // extended standoffs
            if(ext_bottom_standoffs == true) {
                // extended right-rear standoff
                if((width-pcb_loc_x-pcb_width-(gap+2*wallthick) >= 10 || pcb_loc_y >= 10) && ext_bottom_rear_right_enable == true) {
                    normal_standoff = [ext_bottom_standoff[0],
                                        bottom_height+pcb_loc_z+ext_bottom_rear_right_adjust,
                                        ext_bottom_standoff[2],
                                        ext_bottom_standoff[3],
                                        ext_bottom_standoff[4],
                                        ext_bottom_standoff[5],
                                        ext_bottom_standoff[6],
                                        ext_bottom_rear_right_support,
                                        ext_bottom_standoff[8],
                                        ext_bottom_standoff[9],
                                        ext_bottom_standoff[10],
                                        ext_bottom_standoff[11]];
                    translate([width-ext_top_standoff_support_size/4-(2*(wallthick+gap))-(corner_fillet/2),
                        (corner_fillet/2)+ext_top_standoff_support_size/4,0]) standoff(normal_standoff);
                }
                // extended right-front standoff
                if(((width-pcb_loc_x-pcb_width-(gap+2*wallthick) >= 10 && depth-pcb_loc_y-pcb_depth >= 10) || 
                    (width-pcb_loc_x-pcb_width-(gap+2*wallthick) >= 10 && depth-pcb_loc_y-pcb_depth <= 10) ||
                        (width-pcb_loc_x-pcb_width-(gap+2*wallthick) <= 10 && depth-pcb_loc_y-pcb_depth >= 10)) &&
                            ext_bottom_front_right_enable == true) {
                    normal_standoff = [ext_bottom_standoff[0],
                                        bottom_height+pcb_loc_z+ext_bottom_front_right_adjust,
                                        ext_bottom_standoff[2],
                                        ext_bottom_standoff[3],
                                        ext_bottom_standoff[4],
                                        ext_bottom_standoff[5],
                                        ext_bottom_standoff[6],
                                        ext_bottom_front_right_support,
                                        ext_bottom_standoff[8],
                                        ext_bottom_standoff[9],
                                        ext_bottom_standoff[10],
                                        ext_bottom_standoff[11]];
                    translate([width-ext_top_standoff_support_size/4-(corner_fillet/2)-(2*(wallthick+gap)),
                        depth-ext_top_standoff_support_size/4-(corner_fillet/2)-(2*(wallthick+gap)),0]) standoff(normal_standoff);
                }
                // extended left-rear standoff
                if((pcb_loc_x >= 10 || pcb_loc_y >= 10) && ext_bottom_rear_left_enable == true) {
                    normal_standoff = [ext_bottom_standoff[0],
                                        bottom_height+pcb_loc_z+ext_bottom_rear_left_adjust,
                                        ext_bottom_standoff[2],
                                        ext_bottom_standoff[3],
                                        ext_bottom_standoff[4],
                                        ext_bottom_standoff[5],
                                        ext_bottom_standoff[6],
                                        ext_bottom_rear_left_support,
                                        ext_bottom_standoff[8],
                                        ext_bottom_standoff[9],
                                        ext_bottom_standoff[10],
                                        ext_bottom_standoff[11]];
                    translate([(corner_fillet/2)+ext_top_standoff_support_size/4,
                        (corner_fillet/2)+ext_top_standoff_support_size/4,0]) standoff(normal_standoff);
                }
                // extended left-front standoff
                if(((pcb_loc_x >= 10 && depth-(pcb_loc_y+pcb_depth) >= 10) || 
                        (pcb_loc_x <= 10 && depth-(pcb_loc_y+pcb_depth) >= 10) || 
                            (pcb_loc_x >= 10 && depth-(pcb_loc_y+pcb_depth) <= 10)) && 
                                ext_bottom_front_left_enable == true) {
                    normal_standoff = [ext_bottom_standoff[0],
                                        bottom_height+pcb_loc_z+ext_bottom_front_left_adjust,
                                        ext_bottom_standoff[2],
                                        ext_bottom_standoff[3],
                                        ext_bottom_standoff[4],
                                        ext_bottom_standoff[5],
                                        ext_bottom_standoff[6],
                                        ext_bottom_front_left_support,
                                        ext_bottom_standoff[8],
                                        ext_bottom_standoff[9],
                                        ext_bottom_standoff[10],
                                        ext_bottom_standoff[11]];
                    translate([(corner_fillet/2)+ext_top_standoff_support_size/4,
                        depth-ext_top_standoff_support_size/4-(corner_fillet/2)-(2*(wallthick+gap)),0]) 
                            standoff(normal_standoff);
                }
            }
        }
        // subtractive accessories
        if(accessory_name != "none") {
            for (i=[1:11:len(accessory_data[a[0]])-1]) {
                class = accessory_data[a[0]][i];
                type = accessory_data[a[0]][i+1];
                loc_x = accessory_data[a[0]][i+2];
                loc_y = accessory_data[a[0]][i+3];
                loc_z = accessory_data[a[0]][i+4];
                face = accessory_data[a[0]][i+5];
                rotation = accessory_data[a[0]][i+6];
                parametric = accessory_data[a[0]][i+7];
                size_x = accessory_data[a[0]][i+8][0];
                size_y = accessory_data[a[0]][i+8][1];
                size_z = accessory_data[a[0]][i+8][2];
                data = accessory_data[a[0]][i+9];
                mask = accessory_data[a[0]][i+10];

                if ((class == "sub" && face == "bottom") || class == "suball") {
                    if(accessory_highlight == false) {
                        parametric_move_sub(type, loc_x, loc_y, loc_z, face, rotation, parametric,
                            [size_x,size_y,size_z],data, mask);
                    }
                    else {
                        #parametric_move_sub(type,loc_x,loc_y,loc_z,face,rotation,parametric,
                            [size_x,size_y,size_z],data, mask);

                    }
                }
                // create openings for additive 
                if (class == "add2" && face == "bottom" && type == "standoff") {
                    parametric_move_sub("round",loc_x,loc_y,loc_z-.1,face,rotation,parametric,
                        [6.5,size_y,floorthick+1],data,mask);
                }
                if ((class == "add1" || class == "add2") && type == "uart_holder") {
                    if(accessory_highlight == false) {
                            parametric_move_sub("microusb",loc_x+5.25,loc_y-5,loc_z+4,face,rotation,parametric,
                                [0,0,0],data,mask);
                    }
                    else {
                            #parametric_move_sub("microusb",loc_x+5.25,loc_y-5,loc_z+4,face,rotation,parametric,
                                [0,0,0],data,mask);
                    }
                }
                if ((class == "add1" || class == "add2") && face == "bottom" && type == "hc4_oled_holder") {
                    parametric_move_sub("rectangle",loc_x+1,loc_y+1.75,loc_z+25.5,face,rotation,parametric,
                        [26.5,wallthick+gap+4,15],[[.1,.1,.1,.1]],mask);
                }
                if ((class == "add1" || class == "add2") && face == "bottom" && type == "access_port") {
                    if(data[0] == "landscape") {
                        if(rotation[2] == 180) {
                            parametric_move_sub("rectangle",loc_x-6+size_x,loc_y+.5+size_y,loc_z-adj,face,rotation,
                                parametric,[size_x-17,size_y-1,floorthick+1],[[.1,.1,.1,.1]],mask);
                            parametric_move_sub("rectangle",loc_x-size_x+12.5+size_x,loc_y-(size_y/2)+6+size_y,loc_z-adj,
                                face,rotation,parametric,[5.5,10.5,floorthick+.12],[[5.5,5.5,5.5,5.5]],mask);
                        }
                        else {
                            parametric_move_sub("rectangle",loc_x+6,loc_y-.5,loc_z-adj,face,rotation,
                                parametric,[size_x-17,size_y-1,floorthick+1],[[.1,.1,.1,.1]],mask);
                            parametric_move_sub("rectangle",loc_x+size_x-12.5,loc_y+(size_y/2)-6,loc_z-adj,face,rotation,
                                parametric,[5.5,10.5,floorthick+.12],[[5.5,5.5,5.5,5.5]],mask);

                        }
                    }
                    else {
                        if(rotation[2] == 180) {
                            if(data[0] == "portrait") {
                                parametric_move_sub("rectangle",loc_x+size_x-.5,loc_y+size_y-5.75,loc_z-adj,face,
                                    rotation,parametric,[size_x-1,size_y-17,floorthick+1],[[.1,.1,.1,.1]],mask);
                                parametric_move_sub("rectangle",loc_x-(size_x/2)+5+size_x,loc_y-size_y+12.5+size_y,
                                    loc_z-adj,face,rotation,parametric,[10.5,5.5,floorthick+.12],[[5.5,5.5,5.5,5.5]],mask);
                            }
                            else {
                                parametric_move_sub("rectangle",loc_x-.5,loc_y-5.75,loc_z-adj,face,rotation,
                                    parametric,[size_x-1,size_y-17,floorthick+1],[[.1,.1,.1,.1]],mask);
                                parametric_move_sub("rectangle",loc_x-(size_x/2)+5,loc_y-size_y+12.5,loc_z-adj,face,
                                rotation,parametric,[10.5,5.5,floorthick+.12],[[5.5,5.5,5.5,5.5]],mask);
                            }
                        }
                        else {
                            parametric_move_sub("rectangle",loc_x+.5,loc_y+5.75,loc_z-adj,face,rotation,
                                parametric,[size_x-1,size_y-17,floorthick+1],[[.1,.1,.1,.1]],mask);
                            parametric_move_sub("rectangle",loc_x+(size_x/2)-5,loc_y+size_y-12.5,loc_z-adj,face,rotation,
                                parametric,[10.5,5.5,floorthick+.12],[[5.5,5.5,5.5,5.5]],mask);
                        }
                    }
                }
                if ((class == "model") && face == "bottom" && type == "h2_netcard") {
                    parametric_move_sub("rectangle",loc_x+25,loc_y-6,loc_z-14,face,rotation,
                        parametric,[68.5,wallthick+3,14.5],[[1,1,1,1]],mask);
                }
                if ((class == "add1" || class == "add2") && face == "bottom" && type == "button") {
                    if(data[1] == "recess") {
                        #parametric_move_sub("sphere",loc_x,loc_y,loc_z,face,rotation,
                            parametric,[size_x-1,size_y,size_z],data,mask);
                    }
                    if(data[1] == "cutout") {
                        parametric_move_sub("rectangle",loc_x+10,loc_y+4,loc_z-adj,face,rotation,
                            parametric,[size_x+2,size_y+1,size_z+2*adj],[[.1,.1,.1,.1]],mask);
                    }
                }
            }
        }
        // ui access port
        if(bottom_access_port_enable == true) {
//            translate([access_port_location[0],access_port_location[1], floorthick+.12]) 
        }
        // sbc openings
        if(sbc_highlight == true) {
            #translate([pcb_loc_x ,pcb_loc_y,bottom_height-pcb_z+pcb_loc_z-adj]) 
                sbc(sbc_model, cooling, fan_size, gpio_opening, uart_opening, true);
        }
        else {
            translate([pcb_loc_x ,pcb_loc_y,bottom_height-pcb_z+pcb_loc_z-adj]) 
                sbc(sbc_model, cooling, fan_size, gpio_opening, uart_opening, true);
        }
        // indents
        if(indents == true) {

            for (i=[1:11:len(sbc_data[s[0]])-2]) {
                class = sbc_data[s[0]][i+1];
                type = sbc_data[s[0]][i+2];
                id = sbc_data[s[0]][i+3];
                loc_x = sbc_data[s[0]][i+4]+pcb_loc_x;
                loc_y = sbc_data[s[0]][i+5]+pcb_loc_y;
                loc_z = sbc_data[s[0]][i+6]+pcb_loc_z;
                side = sbc_data[s[0]][i+7];
                rotation = sbc_data[s[0]][i+8];

                indent(loc_x, loc_y, bottom_height+pcb_loc_z-adj, rotation[2], side, class, type, wallthick, gap, floorthick, pcb_z);
            }   
        }
        // clean fillets
        if(case_design == "shell") {
            translate([(width/2)-wallthick-gap,(depth/2)-wallthick-gap,bottom_height/2]) 
                cube_negative_fillet([width,depth,bottom_height], radius=-1,
                    vertical=[corner_fillet,corner_fillet,corner_fillet,corner_fillet], top=[0,0,0,0], 
                            bottom=[edge_fillet,edge_fillet,edge_fillet,edge_fillet,edge_fillet], $fn=90);
        }
    }
    // additive accessories
    if(accessory_name != "none") {
        for (i=[1:11:len(accessory_data[a[0]])-1]) {
            class = accessory_data[a[0]][i];
            type = accessory_data[a[0]][i+1];
            loc_x = accessory_data[a[0]][i+2];
            loc_y = accessory_data[a[0]][i+3];
            loc_z = accessory_data[a[0]][i+4];
            face = accessory_data[a[0]][i+5];
            rotation = accessory_data[a[0]][i+6];
            parametric = accessory_data[a[0]][i+7];
            size = accessory_data[a[0]][i+8];
            data = accessory_data[a[0]][i+9];
            mask = accessory_data[a[0]][i+10];

            if(class == "add2" && face == "bottom") {
                parametric_move_add(type,loc_x,loc_y,loc_z,face,rotation,parametric,size,data,mask);
            }
        }
    }
}
