Refined Typeatron model. Getting close to a version precise enough for the one-shot Shapeways order

function pythag(a, b) = sqrt(a*a + b*b);
function angle(a, b) = atan(a/b);

includeInternalComponents = true;

// this is the accuracy value for Shapeways' "Strong & Flexible Plastics" option
error = 0.15;

// note: AFAIK, "clearance" is a minimum gap in printed parts.  Here, however, it is used
// as a lesser/safer accuracy for gaps between the printed part and foreign objects such as
// circuit boards, which may not have been cut or measured with the same degree of precision.
clearance = 0.5;

containmentWallThick = 1;

nanoLength = 43.2;
nanoWidth = 18.0;
nanoHeightWithoutUsb = 5.4;
nanoHeightToUsbBase = 3.3;
nanoUsbWidth = 7.6;
nanoUsbHeight = 3.9;
nanoLeftMargin = 5;

chargerHeaderLength = 5.10;
chargerHeaderWidth = 2.56;

powerSwitchLength = 11.6;
powerSwitchWidth = 4.0;
powerSwitchDepth = 7.5;
powerSwitchOffset = 12;

caseWidth = 70;
caseLength = 130;
caseHeight = 11;

wallThick = caseHeight/2;
lidThick = 1.5;
floorThick = 1.5;
lidMargin = 1;

fingerHeightOffset = 5;
fingerWellDepth = 10;
fingerRad = 15;
thumbWellDepth = wallThick;
thumbWellRadius = 30;
pushButtonWellWidth = 7;
pushButtonWellDepth = 4;
pushButtonBaseThick = 1;
pushButtonLegLength = 4;
pushButtonRadius = 3.5/2;
pushButtonLegProtrusion = pushButtonLegLength - pushButtonBaseThick;
buttonThick = 8;
buttonPressDepth = 0.3;
buttonWidth = pushButtonWellWidth;
buttonLength = 25;
buttonStabilizerWellWidth = 3;
buttonStabilizerRodHeight = pushButtonWellDepth - 1;
totalFingerWellDepth = fingerWellDepth + buttonThick/2 + buttonPressDepth + pushButtonWellDepth;
totalThumbWellDepth = thumbWellDepth + buttonThick/2 + buttonPressDepth + pushButtonWellDepth;

ledDomeRadius = 2.6;
ledRimRadius = 3.1;

thumbBevelLength = 48;
thumbBevelWidth = 31;

thumbBevelAngle = angle(thumbBevelLength-wallThick,thumbBevelWidth-wallThick);
thumbBevelStretch = pythag(thumbBevelLength-wallThick, thumbBevelWidth-wallThick);

thumbKeyOffset = 23;

cavityWidth = caseWidth - wallThick - totalFingerWellDepth - pushButtonBaseThick;
cavityLength = caseLength - (2 * wallThick);

lidWidth = caseWidth - wallThick + lidMargin - totalFingerWellDepth + 3;
lidLength = caseLength - thumbBevelLength - wallThick + 2*lidMargin;

// button well with origin at the center of the base of the switch
// legs of the switch run along the x axis
module pushButtonWell(depth) {
    translate([-pushButtonWellWidth/2, -pushButtonWellWidth/2, 0]) {

		// square well for body of switch
        cube([pushButtonWellWidth,pushButtonWellWidth, depth]);

		// channels for legs/wires of switch
        translate([0,0,-pushButtonLegLength]) {
                translate([-1,0,0]) {
                    cube([2,2,depth+pushButtonLegLength]);
                }
                translate([pushButtonWellWidth-1,0, 0]) {
                    cube([2,2,depth+pushButtonLegLength]);
                }
                translate([-1,pushButtonWellWidth-2, 0]) {
                    cube([2,2,depth+pushButtonLegLength]);
                }
                translate([pushButtonWellWidth-1,pushButtonWellWidth-2, 0]) {
                    cube([2,2,depth+pushButtonLegLength]);
                }
        }
    }

    // rectangular well for button body, and stabilizer wells
    translate([-buttonLength/2,-buttonWidth/2,pushButtonWellDepth]) {
        cube([buttonLength,buttonWidth,buttonThick+buttonPressDepth+10]);

        translate([0,0,-pushButtonWellDepth]) {
            cube([buttonStabilizerWellWidth, buttonWidth, pushButtonWellDepth]);
		}

        translate([buttonLength-buttonStabilizerWellWidth,0,-pushButtonWellDepth]) {
            cube([buttonStabilizerWellWidth, buttonWidth, pushButtonWellDepth]);
		}
    }
}

module fingerWell(depth, radius) {
    translate([radius - depth,0,0]) {
        cylinder(h=caseHeight,r=radius);
    }

    translate([radius - depth, 0, wallThick]) {
        cylinder(h=wallThick+.001, r1=radius-wallThick/2, r2=radius+wallThick/2);
    }

    translate([radius - depth,0,0]) {
        cylinder(h=wallThick+.001, r2=radius-wallThick/2, r1=radius+wallThick/2);
    }
}

// create the lid
// buffer: hyper-extends the lid, for better rendering
// shrinkage: clearance around the edges of the lid
module lid(buffer, shrinkage) {
    translate([0,0,-buffer]) {
        translate([wallThick-lidMargin+shrinkage,wallThick-lidMargin+shrinkage,0]) {
            cube([lidWidth,lidLength,lidThick+buffer]);
        }
        translate([thumbBevelWidth,wallThick-lidMargin+shrinkage,0]) {
            cube([lidWidth-thumbBevelWidth+wallThick,cavityLength+(lidMargin-shrinkage)*2,lidThick+buffer]);
        }

        // note: currently no "shrinkage" on this edge
        translate([thumbBevelWidth,caseLength-wallThick,caseHeight]) {
            rotate([0,0,180+thumbBevelAngle]) {
                rotate([0,90,0]) {
                    translate([0,0,thumbKeyOffset]) {
                        rotate([0,90,-90]) {
                            translate([0,wallThick,wallThick-totalThumbWellDepth]) {
                                rotate([180,0,0]) {
                                    translate([-27,-wallThick,pushButtonBaseThick]) {
                                        translate([0,0,-6]) {
                                            cube([47,lidThick+buffer,20]);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

module screwHoles() {
    translate([0,0,-1]) {
        translate([15,caseLength-thumbBevelLength-wallThick+9,0]) { cylinder(h=caseHeight+2,r=1.5); }

        translate([wallThick+cavityWidth+3.5,caseLength-fingerHeightOffset-fingerRad*2,0]) { cylinder(h=caseHeight+2,r=1.5); }
        translate([wallThick+cavityWidth+3.5,caseLength-fingerHeightOffset-fingerRad*4,0]) { cylinder(h=caseHeight+2,r=1.5); }
        translate([wallThick+cavityWidth+3.5,caseLength-fingerHeightOffset-fingerRad*6,0]) { cylinder(h=caseHeight+2,r=1.5); }
    }
}

difference() {
    // basic shape of the case
    union() {
		// box with thumb bevel
        difference() {
            translate([wallThick, wallThick,0]) {
                cube([caseWidth-caseHeight,caseLength-caseHeight,caseHeight]);
            }
            translate([thumbBevelWidth,caseLength-wallThick,-1]) {
                rotate([0,0,thumbBevelAngle]) {
                    rotate([0,-90,0]) {
                        cube([caseHeight+1, 100, thumbBevelStretch]);
                    }
                }
            }
        }

        translate([wallThick,wallThick,wallThick]) {
            sphere(wallThick);
            rotate([-90,0,0]) {
                cylinder(h=caseLength-thumbBevelLength-wallThick, r=wallThick);
            }
            rotate([0,90,0]) {
                cylinder(h=caseWidth-caseHeight, r=wallThick);
            }
        }
        translate([caseWidth-wallThick,wallThick,wallThick]) {
            sphere(wallThick);
            rotate([-90,0,0]) {
                cylinder(h=caseLength-caseHeight, r=wallThick);
            }
        }
        translate([caseWidth-wallThick,caseLength-wallThick,wallThick]) {
            sphere(wallThick);
        }

		// thumb bevel
		translate([wallThick,caseLength-thumbBevelLength,wallThick]) {
            sphere(wallThick);
        }
        translate([thumbBevelWidth,caseLength-wallThick,wallThick]) {
            sphere(wallThick);
            rotate([0,90,0]) {
                cylinder(h=caseWidth-thumbBevelWidth-wallThick, r=wallThick);
            }
            rotate([0,0,180+thumbBevelAngle]) {
                rotate([0,90,0]) {
                    cylinder(h=thumbBevelStretch, r=wallThick);
                }
            }
        }
    }

    // inner compartment
    translate([wallThick,wallThick,0]) {
        cube([cavityWidth,caseLength-thumbBevelLength-wallThick,caseHeight-floorThick]);
    }
    translate([thumbBevelWidth+2,wallThick,0]) {
        cube([cavityWidth-thumbBevelWidth+wallThick-2,cavityLength,caseHeight-floorThick]);
    }

    // depression for lid
    lid(1,0);

    screwHoles();

    // finger button wells
    for (i = [0:3]) {
        translate([
            caseWidth,
            caseLength - fingerHeightOffset - fingerRad * (1 + 2 * i),
        0]) {

            fingerWell(fingerWellDepth, fingerRad);

            // well and channels for push button switch and wires
            translate([-totalFingerWellDepth,0,caseHeight/2]) {
                rotate([0,90,0]) { rotate([0,0,90]) {
                    pushButtonWell(pushButtonWellDepth+fingerRad);
                }}
            }
        }
    }

    // thumb button well
    translate([thumbBevelWidth,caseLength-wallThick,caseHeight]) {
        rotate([0,0,180+thumbBevelAngle]) {
            rotate([0,90,0]) {
                translate([0,0,thumbKeyOffset]) {
                    rotate([0,90,0]) { rotate([0,0,-90]) {
                        //cube([50,100,200]);

                        translate([wallThick,0,0]) {
                            fingerWell(thumbWellDepth, thumbWellRadius);
                        }
                    }}

                    rotate([0,90,-90]) {
                        translate([0,wallThick,wallThick-totalThumbWellDepth]) {
                            pushButtonWell(pushButtonWellDepth+100);

                            rotate([180,0,0]) {
                                translate([-27,-wallThick-1,pushButtonBaseThick]) {
                                    cube([39,caseHeight-floorThick+1,15]);
                                    cube([22,caseHeight-floorThick+1,20]);
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    // hole for status LED
    translate([cavityWidth+wallThick-ledRimRadius-3,caseLength+1,wallThick]) {
    	    rotate(a=[90,0,0]) {
            cylinder(h=wallThick+2,r=ledDomeRadius);

            translate([0,0,wallThick]) {
                cylinder(h=10+1,r=ledRimRadius);
            }
        }
    }

    // hole for battery charger headers
	translate([wallThick,0,caseHeight-floorThick-chargerHeaderLength-2*error]) {
        cube([chargerHeaderWidth+2*error,wallThick,chargerHeaderLength+2*error]);
    }

    // hole for SPDT Mini Power Switch
    translate([powerSwitchOffset,0,wallThick-powerSwitchWidth/2-error]) {
        cube([powerSwitchLength+2*error,wallThick,powerSwitchWidth+2*error]);
    }

    // hole for USB port
    translate([wallThick+cavityWidth-nanoLeftMargin-nanoWidth/2-nanoUsbWidth/2-clearance,0,caseHeight-floorThick-nanoHeightToUsbBase-nanoUsbHeight-clearance]) {
        cube([nanoUsbWidth+2*clearance,wallThick,nanoUsbHeight+clearance]);
    }
    // trim off the thin remainder above the USB port which would be problematic to print,
    // and make it harder to get the Nano into its socket anyway
    translate([wallThick+cavityWidth-nanoLeftMargin-nanoWidth/2-nanoUsbWidth/2-clearance,wallThick-lidMargin,0]) {
        cube([nanoUsbWidth+2*clearance,lidMargin,2]);
    }
}

// lid
translate([0,0,caseHeight + 2]) {
    difference() {
       // the gap of 0.4 was determined by taking into account the 0.15mm accuracy of
       // the device and the 0.15% error by longest axis of the material, keeping in mind
	   // that there are always a pair of gaps across the lid from each other.
       // 0.4mm is actually larger than necessary in the horizontal (narrower) dimension.
       lid(0,0.4);

       screwHoles();
    }
}

// buttons
// Note: the buttons are oriented so as to make the longest surfaces the most smooth
translate([-5,0,10]) {
    for (i = [0:4]) {
        translate([0,i*(buttonLength+2),0]) { rotate([90,180,-90]) {
            //cube([10,20,40]);

            difference() {
                union() {
                    translate([0,buttonWidth/2,buttonWidth/2]) {
                        rotate([0,90,0]) { cylinder(h=buttonLength,r=buttonWidth/2); }
                    }

                    translate([0,0,buttonWidth/2]) {
                        cube([buttonLength,buttonWidth,buttonThick-buttonWidth/2]);
                    }

                    translate([0,0,buttonThick]) {
                        cube([buttonStabilizerWellWidth, buttonWidth, buttonStabilizerRodHeight]);
		            }

                    translate([buttonLength-buttonStabilizerWellWidth,0,buttonThick]) {
                        cube([buttonStabilizerWellWidth, buttonWidth, buttonStabilizerRodHeight]);
		            }
                }

                translate([buttonLength/2,buttonWidth/2,buttonThick-0.5]) {
                    cylinder(h=1,r=pushButtonRadius);
                }
            }
        }}
    }
}

// electronic components
translate([wallThick,wallThick,0]) {
    // power switch
    translate([powerSwitchOffset-wallThick,0,wallThick-powerSwitchWidth/2-error]) {
        translate([-containmentWallThick,0,0]) {
            cube([containmentWallThick,powerSwitchDepth-wallThick+error+containmentWallThick,caseHeight-floorThick-wallThick+powerSwitchWidth/2+error]);
        }
        translate([powerSwitchLength+2*error,0,0]) {
            cube([containmentWallThick,powerSwitchDepth-wallThick+error+containmentWallThick,caseHeight-floorThick-wallThick+powerSwitchWidth/2+error]);
        }
        translate([-containmentWallThick,0,powerSwitchWidth+2*error]) {
            cube([powerSwitchLength+2*(containmentWallThick+error),powerSwitchDepth-wallThick+error+containmentWallThick,caseHeight-floorThick-wallThick-powerSwitchWidth/2-error]);
        }
        translate([-containmentWallThick,powerSwitchDepth-wallThick+error,powerSwitchWidth+2*error-1]) {
            cube([powerSwitchLength+2*(containmentWallThick+error),containmentWallThick,1]);
        }
    }

    // Arduino Nano v3.0
    translate([cavityWidth-nanoLeftMargin-nanoWidth,0,0]) {
        if (includeInternalComponents) {
            translate([0,0,-10]) {
                cube([nanoWidth,nanoLength,nanoHeightWithoutUsb]);
            }
        }

        translate([0,0,caseHeight-floorThick-nanoHeightToUsbBase-error]) {
            translate([-containmentWallThick-clearance,0,0]) {
                cube([containmentWallThick,nanoLength+clearance+containmentWallThick,nanoHeightToUsbBase+error]);
            }
            translate([nanoWidth+clearance,0,0]) {
                cube([containmentWallThick,nanoLength+clearance+containmentWallThick,nanoHeightToUsbBase+error]);
            }
            translate([-containmentWallThick-clearance,nanoLength+clearance,0]) {
                cube([nanoWidth+2*(clearance+containmentWallThick),containmentWallThick,nanoHeightToUsbBase+error]);
            }
        }
    }

    if (includeInternalComponents) {
    // Surface Transducer - Small
    translate([thumbBevelWidth-wallThick+4,caseLength-2*wallThick-21.4-4,-10]) {
       cube([13.8,21.4,7.9]);
    }
    // Bluetooth Modem - BlueSMiRF Silver -- 42.0 x 16.0 x 3.9
    translate([1,31,-10]) { cube([16,42,3.9]); }
    // Polymer Lithium Ion Battery - 110mAh
    translate([-40,3,-10]) { cube([12,28,5.7]); }
    // Polymer Lithium Ion Battery - 400mAh
	translate([18,47,-10]) { cube([25,35,5]); }
    // Triple Axis Accelerometer & Gyro Breakout - MPU-6050
    translate([1,4,-10]) { cube([15.5, 25.7, 2.5]); }
    }
}

function pythag(a, b) = sqrt(a*a + b*b);
function angle(a, b) = atan(a/b);

caseWidth = 70;
caseLength = 130;
caseHeight = 11;

wallThick = caseHeight/2;
lidThick = 1.5;
floorThick = 1.5;
lidMargin = 1.5;

fingerHeightOffset = 5;
fingerWellDepth = 10;
fingerRad = 15;
thumbWellDepth = wallThick;
thumbWellRadius = 30;
pushButtonWellWidth = 7;
pushButtonWellDepth = 4;
pushButtonBaseThick = 1;
pushButtonLegLength = 4;
pushButtonRadius = 3.5/2;
pushButtonLegProtrusion = pushButtonLegLength - pushButtonBaseThick;
buttonThick = 8;
buttonPressDepth = 1;
buttonWidth = pushButtonWellWidth;
buttonLength = 25;
buttonStabilizerWellWidth = 3;
buttonStabilizerRodHeight = pushButtonWellDepth - 1;
totalFingerWellDepth = fingerWellDepth + buttonThick/2 + buttonPressDepth + pushButtonWellDepth;
totalThumbWellDepth = thumbWellDepth + buttonThick/2 + buttonPressDepth + pushButtonWellDepth;

ledDomeRadius = 2.6;
ledRimRadius = 3.1;

thumbBevelLength = 50;
thumbBevelWidth = 35;

thumbBevelAngle = angle(thumbBevelLength-wallThick,thumbBevelWidth-wallThick);
thumbBevelStretch = pythag(thumbBevelLength-wallThick, thumbBevelWidth-wallThick);

thumbKeyOffset = 23;

cavityWidth = caseWidth - wallThick - totalFingerWellDepth - pushButtonBaseThick;
cavityLength = caseLength - (2 * wallThick);

lidWidth = caseWidth - wallThick + lidMargin - totalFingerWellDepth + 3;
lidLength = caseLength - thumbBevelLength - wallThick + 2*lidMargin;

// button well with origin at the center of the base of the switch
// legs of the switch run along the x axis
module pushButtonWell(depth) {
    translate([-pushButtonWellWidth/2, -pushButtonWellWidth/2, 0]) {

		// square well for body of switch
        cube([pushButtonWellWidth,pushButtonWellWidth, depth]);

		// channels for legs/wires of switch
        translate([0,0,-pushButtonLegLength]) {
                translate([-1,0,0]) {
                    cube([2,2,depth+pushButtonLegLength]);
                }
                translate([pushButtonWellWidth-1,0, 0]) {
                    cube([2,2,depth+pushButtonLegLength]);
                }
                translate([-1,pushButtonWellWidth-2, 0]) {
                    cube([2,2,depth+pushButtonLegLength]);
                }
                translate([pushButtonWellWidth-1,pushButtonWellWidth-2, 0]) {
                    cube([2,2,depth+pushButtonLegLength]);
                }
        }
    }

    // rectangular well for button body, and stabilizer wells
    translate([-buttonLength/2,-buttonWidth/2,pushButtonWellDepth]) {
        cube([buttonLength,buttonWidth,buttonThick+buttonPressDepth+10]);

        translate([0,0,-pushButtonWellDepth]) {
            cube([buttonStabilizerWellWidth, buttonWidth, pushButtonWellDepth]);
		}

        translate([buttonLength-buttonStabilizerWellWidth,0,-pushButtonWellDepth]) {
            cube([buttonStabilizerWellWidth, buttonWidth, pushButtonWellDepth]);
		}
    }
}

module fingerWell(depth, radius) {
    translate([radius - depth,0,0]) {
        cylinder(h=caseHeight,r=radius);
    }

    translate([radius - depth, 0, wallThick]) {
        cylinder(h=wallThick+.001, r1=radius-wallThick/2, r2=radius+wallThick/2);
    }

    translate([radius - depth,0,0]) {
        cylinder(h=wallThick+.001, r2=radius-wallThick/2, r1=radius+wallThick/2);
    }
}

module lid(buffer, shrinkage) {
    translate([0,0,-buffer]) {
        translate([wallThick-lidMargin+shrinkage,wallThick-lidMargin+shrinkage,0]) {
            cube([lidWidth,lidLength,lidThick+buffer]);
        }
        translate([thumbBevelWidth,wallThick-lidMargin+shrinkage,0]) {
            cube([lidWidth-thumbBevelWidth+wallThick,cavityLength+(lidMargin-shrinkage)*2,lidThick+buffer]);
        }

        // note: currently no "shrinkage" on this edge
        translate([thumbBevelWidth,caseLength-wallThick,caseHeight]) {
            rotate([0,0,180+thumbBevelAngle]) {
                rotate([0,90,0]) {
                    translate([0,0,thumbKeyOffset]) {
                        rotate([0,90,-90]) {
                            translate([0,wallThick,wallThick-totalThumbWellDepth]) {
                                rotate([180,0,0]) {
                                    translate([-27,-wallThick,pushButtonBaseThick]) {
                                        translate([0,0,-6]) {
                                            cube([47,lidThick+buffer,20]);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

module screwHoles() {
    translate([-1,0,0]) {
        translate([17,caseLength-thumbBevelLength-wallThick+9,0]) { cylinder(h=caseHeight+2,r=1.5); }

        translate([wallThick+cavityWidth+3.5,caseLength-fingerHeightOffset-fingerRad*2,0]) { cylinder(h=caseHeight+2,r=1.5); }
        translate([wallThick+cavityWidth+3.5,caseLength-fingerHeightOffset-fingerRad*4,0]) { cylinder(h=caseHeight+2,r=1.5); }
        translate([wallThick+cavityWidth+3.5,caseLength-fingerHeightOffset-fingerRad*6,0]) { cylinder(h=caseHeight+2,r=1.5); }
    }
}

difference() {
    // basic shape of the case
    union() {
		// box with thumb bevel
        difference() {
            translate([wallThick, wallThick,0]) {
                cube([caseWidth-caseHeight,caseLength-caseHeight,caseHeight]);
            }
            translate([thumbBevelWidth,caseLength-wallThick,-1]) {
                rotate([0,0,thumbBevelAngle]) {
                    rotate([0,-90,0]) {
                        cube([caseHeight+1, 100, thumbBevelStretch]);
                    }
                }
            }
        }

        translate([wallThick,wallThick,wallThick]) {
            sphere(wallThick);
            rotate([-90,0,0]) {
                cylinder(h=caseLength-thumbBevelLength-wallThick, r=wallThick);
            }
            rotate([0,90,0]) {
                cylinder(h=caseWidth-caseHeight, r=wallThick);
            }
        }
        translate([caseWidth-wallThick,wallThick,wallThick]) {
            sphere(wallThick);
            rotate([-90,0,0]) {
                cylinder(h=caseLength-caseHeight, r=wallThick);
            }
        }
        translate([caseWidth-wallThick,caseLength-wallThick,wallThick]) {
            sphere(wallThick);
        }

		// thumb bevel
		translate([wallThick,caseLength-thumbBevelLength,wallThick]) {
            sphere(wallThick);
        }
        translate([thumbBevelWidth,caseLength-wallThick,wallThick]) {
            sphere(wallThick);
            rotate([0,90,0]) {
                cylinder(h=caseWidth-thumbBevelWidth-wallThick, r=wallThick);
            }
            rotate([0,0,180+thumbBevelAngle]) {
                rotate([0,90,0]) {
                    cylinder(h=thumbBevelStretch, r=wallThick);
                }
            }
        }
    }

    // inner compartment
    translate([wallThick,wallThick,0]) {
        cube([cavityWidth,caseLength-thumbBevelLength-wallThick,caseHeight-floorThick]);
    }
    translate([thumbBevelWidth+2,wallThick,0]) {
        cube([cavityWidth-thumbBevelWidth+wallThick-2,cavityLength,caseHeight-floorThick]);
    }

    // depression for lid
    lid(1,0);

    screwHoles();

    // finger button wells
    for (i = [0:3]) {
        translate([
            caseWidth,
            caseLength - fingerHeightOffset - fingerRad * (1 + 2 * i),
        0]) {

            fingerWell(fingerWellDepth, fingerRad);

            // well and channels for push button switch and wires
            translate([-totalFingerWellDepth,0,caseHeight/2]) {
                rotate([0,90,0]) { rotate([0,0,90]) {
                    pushButtonWell(pushButtonWellDepth+fingerRad);
                }}
            }
        }
    }

    // thumb button well
    translate([thumbBevelWidth,caseLength-wallThick,caseHeight]) {
        rotate([0,0,180+thumbBevelAngle]) {
            rotate([0,90,0]) {
                translate([0,0,thumbKeyOffset]) {
                    rotate([0,90,0]) { rotate([0,0,-90]) {
                        //cube([50,100,200]);

                        translate([wallThick,0,0]) {
                            fingerWell(thumbWellDepth, thumbWellRadius);
                        }
                    }}

                    rotate([0,90,-90]) {
                        translate([0,wallThick,wallThick-totalThumbWellDepth]) {
                            pushButtonWell(pushButtonWellDepth+100);

                            rotate([180,0,0]) {
                                translate([-27,-wallThick-1,pushButtonBaseThick]) {
                                    cube([39,caseHeight-floorThick+1,15]);
                                    cube([22,caseHeight-floorThick+1,20]);
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    // hole for status LED
    translate([cavityWidth+wallThick-ledRimRadius-3,caseLength+1,wallThick]) {
    	    rotate(a=[90,0,0]) {
            cylinder(h=wallThick+2,r=ledDomeRadius);

            translate([0,0,wallThick]) {
                cylinder(h=10+1,r=ledRimRadius);
            }
        }
    }

    // hole for battery charger headers
	translate([wallThick+cavityWidth-3,-1,wallThick]) {
        translate([-2,0,-3.5]) { cube([4,wallThick+2,7]); }
    }

    // hole for USB port
    translate([31,0,wallThick-2.5]) {
        cube([8,wallThick,5]);
    }

    // socket for SPDT slide switch
    translate([10,0,wallThick-2.25]) {
        cube([12,wallThick,4.5]);
    }
}

// lid
translate([0,0,50]) {
    difference() {
       lid(0,0.5);

       screwHoles();
    }
}

// buttons
translate([caseWidth+30,wallThick,wallThick]) {
    for (i = [0:4]) {
        translate([0,i*2*fingerRad,0]) { rotate([0,-90,0]) { rotate([0,0,90]) {
            //cube([10,20,40]);

            difference() {
                union() {
                    translate([0,buttonWidth/2,buttonWidth/2]) {
                        rotate([0,90,0]) { cylinder(h=buttonLength,r=buttonWidth/2); }
                    }

                    translate([0,0,buttonWidth/2]) {
                        cube([buttonLength,buttonWidth,buttonThick-buttonWidth/2]);
                    }

                    translate([0,0,buttonThick]) {
                        cube([buttonStabilizerWellWidth, buttonWidth, buttonStabilizerRodHeight]);
		            }

                    translate([buttonLength-buttonStabilizerWellWidth,0,buttonThick]) {
                        cube([buttonStabilizerWellWidth, buttonWidth, buttonStabilizerRodHeight]);
		            }
                }

                translate([buttonLength/2,buttonWidth/2,buttonThick-1]) {
                    cylinder(h=2,r=pushButtonRadius);
                }
            }
        }}}
    }
}

// electronic components (for visualization only; comment out before printing!)
translate([wallThick,wallThick,lidThick]) {
    // Arduino Nano v3.0
    translate([22,1,0]) { cube([18.5,43.2,1]); }
    // Bluetooth Modem - BlueSMiRF Silver
    translate([1,1,0]) { cube([16.6,45,3.9]); }
    // Surface Transducer - Small
    translate([1,50,0]) { cube([14.5,21.5,7.9]); }
    // Polymer Lithium Ion Battery - 110mAh
    translate([-40,3,0]) { cube([12,28,5.7]); }
    // Polymer Lithium Ion Battery - 400mAh
	translate([18,47,0]) { cube([25,35,5]); }

    // TODO: MPU-6050 breakout board
}


Delete pahar_vero.scad

Delete pahar_vero.scad

pahar_sampanie(raza_baza = 50, grosime_baza = 5, raza_picior = 3, inaltime_picior = 100, raza_cupa = 50, grosime_perete = 2);

//----------------------------------------------------
module baza_pahar(raza_baza, grosime_baza, raza_picior)
{
    cylinder(h = grosime_baza, r1 = raza_baza, r2 = raza_picior);
}
//----------------------------------------------------
module picior_pahar(inaltime_picior, raza_picior)
{
   cylinder(h = inaltime_picior, r = raza_picior);
}
//----------------------------------------------------
module cupa_pahar(raza_cupa, grosime_perete)
{
    difference(){
        sphere(r = raza_cupa);
        translate ([- raza_cupa, -raza_cupa, 0]) cube([2 * raza_cupa, 2 * raza_cupa, raza_cupa]);

        sphere(r = raza_cupa - grosime_perete);
    }
}
//----------------------------------------------------
module pahar_sampanie(raza_baza, grosime_baza, raza_picior, inaltime_picior, raza_cupa, grosime_perete)
{
    baza_pahar(raza_baza, grosime_baza, raza_picior);
    translate ([0, 0, grosime_baza]) picior_pahar(inaltime_picior, raza_picior);
    translate ([0, 0, grosime_baza + inaltime_picior + raza_cupa]) cupa_pahar(raza_cupa, grosime_perete);
}

tresolution = 50;

radius = 80;

height = 10;

Message = "Bine ați venit la...";

To = "Pagina Vero";

$fn = resolution;

scale([1, 0.5]) difference() {
    cylinder(r =radius , h = 2 * height, center = true);
    translate([0, 0, height])
        cylinder(r = radius - 10, h = height + 1, center = true);
}
linear_extrude(height = height) {
    translate([0, --4]) text(Message, halign = "center");
    translate([0, -16]) text(To, halign = "center");
}

$fn = 100;
number_of_holes = 10;

for(i = [1 : 360 / number_of_holes : 360]) {

    make_cylinder(i);
}

module make_cylinder(i) {

    rotate([0, 0, i]) translate([100, 0, 0]) cylinder(h = 4, r = 20);
}


hardware tweaks

hardware tweaks

use <marv_hat.scad>
use <batteries.scad>
use <raspberrypi.scad>
use <tft.scad>
use <MCAD/boxes.scad>
use <powerboost.scad>
use <switches.scad>
use <boardholder.scad>

$fn=20;

function vecmax (a,b) = [for (i=[0:len(a)]) max(a[i],b[i])];

module halfRoundedBox(d, r) {
    epsilon = 0.01;
    difference() {
        roundedBox(d, r);
        translate([-epsilon, -epsilon, d[2]/2])
            cube([d[0] + epsilon * 4,
                d[1] + epsilon * 4,
                d[2]], center=true);
    }
}

module halfRoundedShell(d, r, t) {
    difference() {
        halfRoundedBox(d, r);
        translate([0,0,t]) halfRoundedBox([d[0]-t*2,d[1]-t*2,d[2]], r);
    }
}

module standoff(x, y, h, d1, d2) {
    translate([x, y, 0]) {
        difference() {
            cylinder(d=d1, h=h);
            cylinder(d=d2, h=h);
        }
    }
}

module wall_standoff(x, y, z, rz, w, h1, h2, d1, d2) {
    epsilon = 0.01;
    translate([x, y, z]) rotate([0, 0, rz]) {
        difference() {
            hull() {
                cylinder(d=d1, h=h1);
                translate([-d1/2,0,0]) cube([d1, w, h1]);
                translate([-d1/2,w,-h2]) cube([d1, w, h2]);
            }
            translate([0, 0, h1-h2]) cylinder(d=d2, h=h2);
            translate([-d1/2 - epsilon, w, -h2 - epsilon])
                cube([d1 + 2 * epsilon, w + epsilon, h1 + h2 + 2 * epsilon]);
        }
    }
}

module quadstandoff(dx, dy, h, d1, d2) {
    for (x=[-dx,dx]/2, y=[-dy,dy]/2)
        standoff(x, y, h, d1, d2);
}

module case(with_exhaust = 1) {
    std_pitch = 2.54;
    pi_standoff_diameter = 5;
    pi_hull_dimensions = [60, 90, 20];
    hat_hull_dimensions = [72, 50, 28];
    corner_radius = 1;
    wall_thickness = 1.5;
    side_spacing = [5, 14, 38]; //38

    // raspberry pi component support
    pi_standoffs = [49, 58];
    pi_standoff_height = 6;
    pi_offset = [0, -14, 0];

    // marv hat component support
    hat_standoffs = [64.92, 45.72, 12.4 + pi_standoff_height];
    hat_standoff_height = 12.4 + pi_standoff_height;
    hat_offset = [0, -19.4, 0];

    // tft component support
    tft_standoffs = [61, 35.56, 21.3 + pi_standoff_height];
    tft_standoff_height = 22.3 + pi_standoff_height;
    tft_offset = [0, 26, 0];

    standoff_outer = 5;
    standoff_inner = 1.75;
    bottom_offset = [0, 0, wall_thickness];
    case_hull_dimensions = vecmax(pi_hull_dimensions, hat_hull_dimensions) + side_spacing;

    module fan_cutout(x, z, r, s) {
        $fn = 50;
        epsilon = 0.01;
        screw_inner = 2.4;
        h = wall_thickness * 3 + 2 * epsilon;
        translate([0, 0, 0])
            cylinder(h = h, r = r);
        for (x = [-s, s], y = [-s, s])
            translate([x, y, 0])
                cylinder(d = screw_inner, h = h);
    }

    module exhaust_cutout() {
        for (x = [-11 : 11], y = [-4 : 4]) {
            translate([x * 3, y * 3, 0])
                cylinder(d = 2, h = 4);
        }
    }

    module bottom_screwholes(dx, dy) {
        for (x = [-dx/2, dx/2], y = [-dy/2, dy/2]) {
            translate([x, y, 0])
                cylinder(d = 2.9, h = 3);
        }
    }

    module teensy_usb_cutout() {
        cube([12, 6, 8], center=true);
    }

    module power_cutout() {
        cylinder(d=8, h=8);
    }

    module bottom () {
        difference() {
            translate ([0, 0, case_hull_dimensions[2] / 2])
                halfRoundedShell(case_hull_dimensions, corner_radius, wall_thickness);
            translate([0, -48, 16]) rotate([90, 0, 0])
                fan_cutout(0, 0, 12.1, 10);
            if (with_exhaust) {
                color("red") translate([0, 53, 16]) rotate([90, 0, 0])
                    exhaust_cutout();
            }
            color("red") translate([0, 10, -1])
                bottom_screwholes(50, 50);
            color("red") translate([11.5, -51, 35])
                teensy_usb_cutout();
            color("red") translate([25, -48, 10]) rotate([90, 0, 0])
                power_cutout();
        }
    }

    module sqstandoff(dxdy, h)
        quadstandoff(dxdy[0], dxdy[1], h, standoff_outer, standoff_inner);

    translate([0,0,0]) bottom();

    translate(pi_offset + bottom_offset)
        sqstandoff(pi_standoffs, pi_standoff_height);

    module hat_standoffs(pos) {
        h = 4;
        w = 5;
        wall_standoff(pos[0]/2, pos[1]/2, pos[2] - h, -90, w, h, h,
            standoff_outer, standoff_inner);
        wall_standoff(-pos[0]/2, pos[1]/2, pos[2] - h, 90, w, h, h,
            standoff_outer, standoff_inner);
        wall_standoff(-pos[0]/2, -pos[1]/2, pos[2] - h, 90, w, h, h,
            standoff_outer, standoff_inner);
        wall_standoff(pos[0]/2, -pos[1]/2, pos[2] - h, -90, w, h, h,
            standoff_outer, standoff_inner);
    }

    //translate(hat_offset + bottom_offset)
    //    sqstandoff(hat_standoffs, hat_standoff_height);
    translate(hat_offset + bottom_offset)
        hat_standoffs(hat_standoffs);

    module tft_wall_standoff(x, y, z, rz)
        wall_standoff(x, y, z, rz, 8, 4, 8,
            standoff_outer, standoff_inner);

    module tft_wall_standoffs(pos) {
        wall_standoff(pos[0]/2, pos[1]/2, pos[2], -90, 7, 4, 8,
            standoff_outer, standoff_inner);
        wall_standoff(-pos[0]/2, pos[1]/2, pos[2], 90, 7, 4, 4,
            standoff_outer, standoff_inner);
        wall_standoff(-pos[0]/2, -pos[1]/2, pos[2], 90, 7, 4, 4,
            standoff_outer, standoff_inner);
        wall_standoff(pos[0]/2, -pos[1]/2, pos[2], -90, 7, 4, 8,
            standoff_outer, standoff_inner);
    }

    module gps_wall_standoffs() {
        for (y=[2.27, -0.27-(2.54*7)])
            wall_standoff(-33.27, y, 22.3 + pi_standoff_height, 90, 4, 4, 4,
                standoff_outer, standoff_inner);
    }

    //translate(tft_offset + bottom_offset)
    //    sqstandoff(tft_standoffs, tft_standoff_height);
    translate(tft_offset + bottom_offset)
        tft_wall_standoffs(tft_standoffs);

    gps_wall_standoffs();

    module faceplate_standoffs(pos) {
        h = 4;
        w = 2;
        wall_standoff(pos[0]/2, pos[1]/2, pos[2] - h, -90, w, h, h,
            standoff_outer, standoff_inner);
        wall_standoff(-pos[0]/2, pos[1]/2, pos[2] - h, 90, w, h, h,
            standoff_outer, standoff_inner);
        wall_standoff(-pos[0]/2, -pos[1]/2, pos[2] - h, 90, w, h, h,
            standoff_outer, standoff_inner);
        wall_standoff(pos[0]/2, -pos[1]/2, pos[2] - h, -90, w, h, h,
            standoff_outer, standoff_inner);
    }

    faceplate_standoffs([case_hull_dimensions[0] - 6,
        case_hull_dimensions[1] - 6, case_hull_dimensions[2]/2]);
}

module components () {
    p = 2.54;
    pi3();
    translate([-p*6, 0, 1.5 + p + 8.5]) rotate([0, 0, 90]) hat(p);
    translate([30, 0, 26]) rotate([0, 0, -90]) tft();
    //translate([20, -50, 16]) rotate([90, 0, 0]) lipo2000(with_wire=1);
    //translate([-45, -50, 34]) rotate([90, 90, 0]) powerboost1000c(has_usb_out=0);
    //translate([37, -30, 7]) rotate([0, 90, 0]) big_toggle_switch();
}

p = 2.54;

//%translate([0,-4,7.5]) rotate([0,0,90]) components();
//%translate([0,35,-3]) rotate([0,0,0]) main_plate();
case(with_exhaust=1);

use <marv_hat.scad>
use <batteries.scad>
use <raspberrypi.scad>
use <tft.scad>
use <MCAD/boxes.scad>
use <powerboost.scad>
use <switches.scad>

$fn=20;

function vecmax (a,b) = [for (i=[0:len(a)]) max(a[i],b[i])];

module halfRoundedBox(d, r) {
    epsilon = 0.01;
    difference() {
        roundedBox(d, r);
        translate([-epsilon, -epsilon, d[2]/2])
            cube([d[0] + epsilon * 4,
                d[1] + epsilon * 4,
                d[2]], center=true);
    }
}

module halfRoundedShell(d, r, t) {
    difference() {
        halfRoundedBox(d, r);
        translate([0,0,t]) halfRoundedBox([d[0]-t*2,d[1]-t*2,d[2]], r);
    }
}

module standoff(x, y, h, d1, d2) {
    translate([x, y, 0]) {
        difference() {
            cylinder(d=d1, h=h);
            cylinder(d=d2, h=h);
        }
    }
}

module wall_standoff(x, y, z, rz, w, h1, h2, d1, d2) {
    epsilon = 0.01;
    translate([x, y, z]) rotate([0, 0, rz]) {
        difference() {
            hull() {
                cylinder(d=d1, h=h1);
                translate([-d1/2,0,0]) cube([d1, w, h1]);
                translate([-d1/2,w,-h2]) cube([d1, w, h2]);
            }
            translate([0, 0, h1-h2]) cylinder(d=d2, h=h2);
            translate([-d1/2 - epsilon, w, -h2 - epsilon])
                cube([d1 + 2 * epsilon, w + epsilon, h1 + h2 + 2 * epsilon]);
        }
    }
}

module quadstandoff(dx, dy, h, d1, d2) {
    for (x=[-dx,dx]/2, y=[-dy,dy]/2)
        standoff(x, y, h, d1, d2);
}

module case(with_exhaust = 1) {
    std_pitch = 2.54;
    pi_standoff_diameter = 5;
    pi_hull_dimensions = [60, 90, 20];
    hat_hull_dimensions = [72, 50, 28];
    corner_radius = 1;
    wall_thickness = 1.5;
    side_spacing = [5, 14, 38];

    // raspberry pi component support
    pi_standoffs = [49, 58];
    pi_standoff_height = 5;
    pi_offset = [0, -14, 0];

    // marv hat component support
    hat_standoffs = [64.92, 44.92, 17.4];
    hat_standoff_height = 17.4;
    hat_offset = [0, -19, 0];

    // tft component support
    tft_standoffs = [61, 35.56, 26.3];
    tft_standoff_height = 27.3;
    tft_offset = [-3, 26, 0];

    standoff_outer = 5;
    standoff_inner = 1.75;
    bottom_offset = [0, 0, wall_thickness];
    case_hull_dimensions = vecmax(pi_hull_dimensions, hat_hull_dimensions) + side_spacing;

    module fan_cutout(x, z, r, s) {
        $fn = 50;
        epsilon = 0.01;
        screw_inner = 2.4;
        h = wall_thickness * 3 + 2 * epsilon;
        translate([0, 0, 0])
            cylinder(h = h, r = r);
        for (x = [-s, s], y = [-s, s])
            translate([x, y, 0])
                cylinder(d = screw_inner, h = h);
    }

    module exhaust_cutout() {
        for (x = [-11 : 11], y = [-4 : 4]) {
            translate([x * 3, y * 3, 0])
                cylinder(d = 2, h = 4);
        }
    }

    module bottom_screwholes(dx, dy) {
        for (x = [-dx/2, dx/2], y = [-dy/2, dy/2]) {
            translate([x, y, 0])
                cylinder(d = 2.9, h = 3);
        }
    }

    module bottom () {
        difference() {
            translate ([0, 0, case_hull_dimensions[2] / 2])
                halfRoundedShell(case_hull_dimensions, corner_radius, wall_thickness);
            translate([0, -48, 18]) rotate([90, 0, 0])
                fan_cutout(0, 0, 12.1, 10);
            if (with_exhaust) {
                color("red") translate([0, 53, 16]) rotate([90, 0, 0])
                    exhaust_cutout();
            }
            color("red") translate([0, 0, -1])
                bottom_screwholes(35, 70);
        }
    }

    module sqstandoff(dxdy, h)
        quadstandoff(dxdy[0], dxdy[1], h, standoff_outer, standoff_inner);

    bottom();

    translate(pi_offset + bottom_offset)
        sqstandoff(pi_standoffs, pi_standoff_height);

    module hat_standoffs(pos) {
        h = 4;
        w = 5;
        wall_standoff(pos[0]/2, pos[1]/2, pos[2] - h, -90, w, h, h,
            standoff_outer, standoff_inner);
        wall_standoff(-pos[0]/2, pos[1]/2, pos[2] - h, 90, w, h, h,
            standoff_outer, standoff_inner);
        wall_standoff(-pos[0]/2, -pos[1]/2, pos[2] - h, 90, w, h, h,
            standoff_outer, standoff_inner);
        wall_standoff(pos[0]/2, -pos[1]/2, pos[2] - h, -90, w, h, h,
            standoff_outer, standoff_inner);
    }

    //translate(hat_offset + bottom_offset)
    //    sqstandoff(hat_standoffs, hat_standoff_height);
    translate(hat_offset + bottom_offset)
        hat_standoffs(hat_standoffs);

    module tft_wall_standoff(x, y, z, rz)
        wall_standoff(x, y, z, rz, 8, 4, 8,
            standoff_outer, standoff_inner);

    module tft_wall_standoffs(pos) {
        wall_standoff(pos[0]/2, pos[1]/2, pos[2], -90, 10, 4, 8,
            standoff_outer, standoff_inner);
        wall_standoff(-pos[0]/2, pos[1]/2, pos[2], 90, 4, 4, 4,
            standoff_outer, standoff_inner);
        wall_standoff(-pos[0]/2, -pos[1]/2, pos[2], 90, 4, 4, 4,
            standoff_outer, standoff_inner);
        wall_standoff(pos[0]/2, -pos[1]/2, pos[2], -90, 10, 4, 8,
            standoff_outer, standoff_inner);
    }

    module gps_wall_standoffs() {
        for (y=[2.27, -0.27-(2.54*7)])
            wall_standoff(-33.27, y, 27.3, 90, 4, 4, 4,
                standoff_outer, standoff_inner);
    }

    //translate(tft_offset + bottom_offset)
    //    sqstandoff(tft_standoffs, tft_standoff_height);
    translate(tft_offset + bottom_offset)
        tft_wall_standoffs(tft_standoffs);

    gps_wall_standoffs();

    module faceplate_standoffs(pos) {
        h = 4;
        w = 2;
        wall_standoff(pos[0]/2, pos[1]/2, pos[2] - h, -90, w, h, h,
            standoff_outer, standoff_inner);
        wall_standoff(-pos[0]/2, pos[1]/2, pos[2] - h, 90, w, h, h,
            standoff_outer, standoff_inner);
        wall_standoff(-pos[0]/2, -pos[1]/2, pos[2] - h, 90, w, h, h,
            standoff_outer, standoff_inner);
        wall_standoff(pos[0]/2, -pos[1]/2, pos[2] - h, -90, w, h, h,
            standoff_outer, standoff_inner);
    }

    faceplate_standoffs([case_hull_dimensions[0] - 6,
        case_hull_dimensions[1] - 6, side_spacing[2] - 5]);
}

module components () {
    p = 2.54;
    pi3();
    translate([-p*6, 0, 1.5 + p + 8.5]) rotate([0, 0, 90]) hat(p);
    translate([30, 3, 26]) rotate([0, 0, -90]) tft();
    //translate([20, -50, 16]) rotate([90, 0, 0]) lipo2000(with_wire=1);
    //translate([-45, -50, 34]) rotate([90, 90, 0]) powerboost1000c(has_usb_out=0);
    //translate([37, -30, 7]) rotate([0, 90, 0]) big_toggle_switch();
}

p = 2.54;

%translate([0,-4,6.5]) rotate([0,0,90]) components();
case();