Another round of tweaks based on a print.

// Adapted from: https://github.com/luisibanez/ShapesFor3DPrinting/tree/master/OpenSCA

// For case
width  = 36;  // x
length = 36;  // y

// For camera cover
flex_adapter_width = 23;   // measures 21mm, but w/ a nominal 22mm opening it was still too tight.
cover_width = 27;
cover_height = 2;

// For rounded corners
radius1 = 10;
radius2 = 4;

piCameraAdapter();
// Comment out translate to see
// back cover in place.
translate([40,0,-8])
    piCameraBackCover();

/////////////////////////////////////////////////////////////////////////////////////
// Modules
//

module piCameraBackCoverBevel(length, clearance) {
    c = clearance;
    hh = cover_height / 2;
    hw = ( cover_width / 2 ) + c;
    he = hw + 1.5 + c;
    l = length / 2;
    polyhedron(
        points = [
            [ hw, -l-c, -hh-c ],
            [ hw,  l+c, -hh-c ],
            [ hw,  l+c, hh ],
            [ hw, -l-c, hh ],
            [ he, -l-c, -hh-c ],
            [ he,  l+c, -hh-c ]
            ],
        faces = [
            [ 5, 1, 0, 4],
            [ 4, 0, 3 ],
            [ 2, 1, 5 ],
            [ 5, 4, 3, 2],
            [ 0, 1, 2, 3],
        ]
    );
}

module piCameraBackCover(for_subtraction=false) {
    indent = ! for_subtraction;
    clearance = for_subtraction ? 0.25 : 0;
    c = 2*clearance;
    cov_l = length-8;
    difference() {
        translate([0,-5,10-cover_height/2])
        difference() {
            translate([0,1,0])
            union() {
                cube(size=[cover_width+c,cov_l+c,cover_height+c],center=true);
                piCameraBackCoverBevel(cov_l, clearance);
                mirror([1,0,0])
                    piCameraBackCoverBevel(cov_l, clearance);
            }
            translate([0,15,0])
                cube(size=[flex_adapter_width-c,15,cover_height+c],center=true);
            if (indent)
                translate([0,8-length/2,cover_height/2+0.5])
                rotate([0,90,0])
                    cylinder(r=1, h=cover_width-4, center=true, $fn=20);
        }
        if (! for_subtraction) {
            cornerRounding();
        }
    }
}

module cableOpening() {
    translate([0,14,8.1])
        cube(size=[17,12,4],center=true);
}

module chipOpening() {
    clearance = 0.5;
    c = 2 * clearance;
    translate([0,-9.5,5])
        cube(size=[8+c,10+c,4],center=true);
}

module lensOpening() {
    clearance = 0.5;
    c = 2 * clearance;
    translate([0,0,2.5])
        cube(size=[8+c,8+c,5+c], center=true);
}

module boardOpening() {
    clearance = 0.3;
    c = 2 * clearance;
    translate([0,-3,7.5])
        cube(size=[25+c,24+c,5], center=true);
}

module cameraFrame() {
    translate([0,0,5])
        cube(size=[width,length,10], center=true);
}

module roundedCorner(r) {
    translate([-r, -r, 0])
    difference() {
        translate([0,0,-50])
            cube(size=[r+0.1,r+0.1,100]);
        cylinder(h=100, r=r, $fn=50, center=true);
    }
}

module cornerRounding() {
    // vertical corners
    translate([width/2,length/2,0])
        roundedCorner(radius1);
    translate([-width/2,length/2,0])
    rotate([0,0,90])
        roundedCorner(radius1);
    translate([-width/2,-length/2,0])
    rotate([0,0,180])
        roundedCorner(radius1);
    translate([width/2,-length/2,0])
    rotate([0,0,-90])
        roundedCorner(radius1);

    // top corners
    translate([-width/2,0,10])
    rotate([0,-90,0])
    rotate([90,0,0])
        roundedCorner(radius2);
    translate([width/2,0,10])
    rotate([90,0,0])
        roundedCorner(radius2);
}

module piCameraAdapter() {
    difference() {
        cameraFrame();
        boardOpening();
        chipOpening();
        cableOpening();
        lensOpening();
        cornerRounding();
        piCameraBackCover(for_subtraction=true);
    }
}

// Adapted from: https://github.com/luisibanez/ShapesFor3DPrinting/tree/master/OpenSCA

// For case
width  = 36;  // x
length = 36;  // y

// For camera cover
flex_adapter_width = 23;   // measures 21mm, but w/ a nominal 22mm opening it was still too tight.
cover_width = 27;
cover_height = 2;

// For rounded corners
radius = 8;

piCameraAdapter();
// Comment out translate to see
// back cover in place.
translate([40,0,-8])
    piCameraBackCover();

/////////////////////////////////////////////////////////////////////////////////////
// Modules
//

module piCameraBackCoverBevel(length, clearance) {
    c = clearance;
    hh = cover_height / 2;
    hw = ( cover_width / 2 ) + c;
    he = hw + 1.5 + c;
    l = length / 2;
    polyhedron(
        points = [
            [ hw, -l-c, -hh-c ],
            [ hw,  l+c, -hh-c ],
            [ hw,  l+c, hh ],
            [ hw, -l-c, hh ],
            [ he, -l-c, -hh-c ],
            [ he,  l+c, -hh-c ]
            ],
        faces = [
            [ 5, 1, 0, 4],
            [ 4, 0, 3 ],
            [ 2, 1, 5 ],
            [ 5, 4, 3, 2],
            [ 0, 1, 2, 3],
        ]
    );
}

module piCameraBackCover(for_subtraction=false) {
    indent = ! for_subtraction;
    clearance = for_subtraction ? 0.3 : 0;
    c = 2*clearance;
    cov_l = length-8;
    difference() {
        translate([0,-5,10-cover_height/2])
        difference() {
            translate([0,1,0])
            union() {
                cube(size=[cover_width+c,cov_l+c,cover_height+c],center=true);
                piCameraBackCoverBevel(cov_l, clearance);
                mirror([1,0,0])
                    piCameraBackCoverBevel(cov_l, clearance);
            }
            translate([0,15,0])
                cube(size=[flex_adapter_width-c,11,cover_height+c],center=true);
            if (indent)
                translate([0,8-length/2,cover_height/2])
                rotate([0,90,0])
                    cylinder(r=1, h=cover_width-0.5, center=true, $fn=20);
        }
        if (! for_subtraction) {
            cornerRounding();
        }
    }
}

module cableOpening() {
    translate([0,14,8.1])
        cube(size=[17,12,4],center=true);
}

module chipOpening() {
    clearance = 0.5;
    c = 2 * clearance;
    translate([0,-9.5,5])
        cube(size=[8+c,10+c,4],center=true);
}

module lensOpening() {
    clearance = 0.5;
    c = 2 * clearance;
    translate([0,0,2.5])
        cube(size=[8+c,8+c,5+c], center=true);
}

module boardOpening() {
    clearance = 0.3;
    c = 2 * clearance;
    translate([0,-3,7.5])
        cube(size=[25+c,24+c,5+clearance], center=true);
}

module cameraFrame() {
    translate([0,0,5])
        cube(size=[width,length,10], center=true);
}

module roundedCorner(r) {
    translate([-r, -r, 0])
    difference() {
        translate([0,0,-50])
            cube(size=[r+0.1,r+0.1,100]);
        cylinder(h=100, r=r, $fn=50, center=true);
    }
}

module cornerRounding() {
    // vertical corners
    translate([width/2,length/2,0])
        roundedCorner(radius);
    translate([-width/2,length/2,0])
    rotate([0,0,90])
        roundedCorner(radius);
    translate([-width/2,-length/2,0])
    rotate([0,0,180])
        roundedCorner(radius);
    translate([width/2,-length/2,0])
    rotate([0,0,-90])
        roundedCorner(radius);

    // top corners
    translate([-width/2,0,10])
    rotate([0,-90,0])
    rotate([90,0,0])
        roundedCorner(radius/2);
    translate([width/2,0,10])
    rotate([90,0,0])
        roundedCorner(radius/2);
}

module piCameraAdapter() {
    difference() {
        cameraFrame();
        boardOpening();
        chipOpening();
        cableOpening();
        lensOpening();
        cornerRounding();
        piCameraBackCover(for_subtraction=true);
    }
}


shapes/stack: support both dist and distances param

use <misc.scad>

// translate children
module lineup(arr=undef)
{
    /*echo(arr);*/
    /*echo($children);*/
    if($children>0)
    {
        for (i = [0 : $children-1])
            translate(arr[i]) children(i);
    }
}

module stack(dist=10, distances=undef)
{
    if(dist == undef && distances != undef)
    {
        for (i = [0:len(separations)-1])
        {
            offset = v_sum(separations,i);
            /*echo("i",i,"offset",offset);*/
            translate ([0,0,offset])
            {
                child(i);
            }
        }
    }
    else if(dist != undef && distances == undef)
    {
      for (i = [0 : $children-1])
          translate([ dist*i, 0, 0 ]) children(i);
    }
}

module orient(zaxes, roll=0)
{
    zaxes = len(zaxes.x) == undef && zaxes.x != undef? [zaxes] : zaxes;
    for(zaxis=zaxes)
    {
        rotate(_orient_angles(zaxis))
        /*rotate(roll*z)*/
            children();
    }
}

module size_align(size=[10,10,10], align=[0,0,0], orient=[0,0,1])
{
    bounds = _rotate_matrix(_orient_angles(orient)) * [size.x,size.y,size.z,1];
    t=hadamard(align, [abs(bounds.x/2),abs(bounds.y/2),abs(bounds.z/2)]);
    translate(t)
    {
        orient(orient)
        {
            children();
        }
    }
}

module cubea(size=[10,10,10], align=[0,0,0], extrasize=[0,0,0], extrasize_align=[0,0,0])
{
    size_align(extrasize,extrasize_align)
    {
        size_align(size,align)
        {
            cube(size+extrasize, center=true);
        }
    }
}

module cuberounda(size=[10,10,10], facets=32, rounding_radius=1, align=[0,0,0], extrasize=[0,0,0], extrasize_align=[0,0,0])
{
    size_align(extrasize,extrasize_align)
    {
        size_align(size,align)
        {
            cuberound(size=size+extrasize, facets=facets, rounding_radius=rounding_radius);
        }
    }
}

module cuberound(size=[20,20,20], rounding_radius=1)
{
    hull()
    for(x=[-(size[0]/2-rounding_radius),(size[0]/2-rounding_radius)])
    for(y=[-(size[1]/2-rounding_radius),(size[1]/2-rounding_radius)])
    for(z=[-(size[2]/2-rounding_radius),(size[2]/2-rounding_radius)])
    translate([x,y,z])
    sphere(r=rounding_radius);
}

module cylindera(
        h=10,
        r=undef,
        r1=undef,
        r2=undef,
        d=undef,
        d1=undef,
        d2=undef,
        align=[0,0,0],
        orient=[0,0,1],
        extra_h=0,
        extra_r=undef,
        extra_d=undef,
        extra_align=[0,0,1],
        round_radius=undef,
        debug=false
        )
{
    pi=3.1415926536;

    useDia = r == undef && (r1 == undef && r2 == undef);

    r1_ = useDia?((d1==undef?undef:d1)/2):r1;
    r2_ = useDia?((d2==undef?undef:d2)/2):r2;
    r_= useDia?d/2:(r==undef?0:r);
    r1r2max = max(r1,r2) == undef ? max(d1,d2)/2 : max(r1,r2);
    r__ = r_==undef? r1r2max : r_;
    extra_r_ = useDia?((extra_d==undef?0:extra_d)/2):((extra_r==undef)?0:extra_r);

    sizexy=r__*2;
    extra_sizexy=extra_r_*2;

    // some orient hax here to properly support extra_align
    orient(-orient)
    size_align([extra_sizexy,extra_sizexy,extra_h], align=extra_align, orient=orient)
    orient(orient)
    {
        if(debug)
        {
            echo(useDia, h, r_, r1_, r2_, extra_r_, align);
        }

        // some orient hax here to properly support extra_align
        orient(-orient)
        size_align([sizexy,sizexy,h], align=align, orient=orient)
        {
            if(round_radius==undef)
            {
                cylinder(h=h+extra_h, r=r_+extra_r_, r1=r1_, r2=r2_, center=true);
            }
            else
            {
                rcylinder(h=h+extra_h, r=r_+extra_r_, r1=r1_, r2=r2_, round_radius=round_radius);
            }
        }
    }
}

/*translate([10,0,0])*/
/*rotate_extrude()*/
        /*translate([10-2,2,0])*/
/*$fa = 5.6;*/
/*$fs = 0.3;*/
/*circle(r = 100);*/
/*torus(10, 2, align=[0,0,0], orient=[0,0,1]);*/

module torus(radius, radial_width, align=[0,0,0], orient=[0,0,1])
{
    size_align(size=[radius*2+radial_width*2, radius*2+radial_width*2, radial_width*2], align=align, orient=orient)
    rotate_extrude()
    translate([radius, 0, 0])
    circle(radial_width);
}

module rcylinder(d=10, r1=undef, r2=undef, h=10, round_radius=2)
{
    r_= (r1!=undef && r2!=undef) ? [r1,r2] : [d/2,d/2];
    /*translate([0,0,-h/2])*/
    hull()
    {
        /*a = r_[0]-r_[1];*/
        /*b = h;*/
        /*c = pythag_hyp(a,b);*/
        /*echo(c);*/
        /*d = c;//pythag_leg(a,c);*/
        /*echo(d);*/
        /*translate([0,r1-round_radius,0])*/
        /*cube([d,d,d]);*/
        /*angle2 = -atan2(-h, r1-r2);*/
        /*echo(angle2);*/
        /*x2 = r2-r1 < 0 ? (round_radius*2*cos(angle2)) : (round_radius*2*sin(angle2));*/
        /*echo(x2)*/
        /*translate([0, 0, h/2-round_radius])*/
        /*torus(radius=r_[1]-round_radius, radial_width=round_radius, align=[0,0,0]);*/

        for(z=[-1,1])
        translate([0, 0, z*(-h/2)])
        {
            /*rd = abs(r1-r2);*/
            /*angle1 = atan2(h, abs(r2-r1));*/
            /*x1 = round_radius*2*cos(angle1);*/
            /*echo(angle1, x1);*/
            r__=z!=-1?r_[0]:r_[1];
            torus(radius=r__-round_radius/2, radial_width=round_radius/2, align=[0,0,z]);

            /*translate([0, 0, -round_radius])*/
            /*cubea([r__*2,r__*2,5], align=[0,0,-z]);*/
        }
    }
}

module pie_slice_shape(r, start_angle, end_angle) {
    R = r * sqrt(2) + 1;
    a0 = (4 * start_angle + 0 * end_angle) / 4;
    a1 = (3 * start_angle + 1 * end_angle) / 4;
    a2 = (2 * start_angle + 2 * end_angle) / 4;
    a3 = (1 * start_angle + 3 * end_angle) / 4;
    a4 = (0 * start_angle + 4 * end_angle) / 4;
    if(end_angle > start_angle)
    {
        intersection() {
            circle(r);
            polygon([
                    [0,0],
                    [R * cos(a0), R * sin(a0)],
                    [R * cos(a1), R * sin(a1)],
                    [R * cos(a2), R * sin(a2)],
                    [R * cos(a3), R * sin(a3)],
                    [R * cos(a4), R * sin(a4)],
                    [0,0]
            ]);
        }
    }
}

module pie_slice(r, start_angle, end_angle, h)
{
    linear_extrude(h)
    {
        pie_slice_shape(r, start_angle, end_angle);
    }
}

module hollow_cylinder(d=10, thickness=1, h=10, taper=false, orient=[0,0,1], align=[0,0,0])
{
    outer_d = d+thickness/2;
    inner_d = d-thickness/2;
    size_align(size=[outer_d, outer_d, h], orient=orient, align=align)
    difference()
    {
        hull()
        {
            taper_h = outer_d/2;
            if(taper)
            {
                for(z=[-1,1])
                translate([0,0,z*h/2])
                mirror([0,0,z==-1?1:0])
                difference()
                {
                    cylindera(d1=outer_d, d2=0, h=taper_h, align=[0,0,1]);
                    cylindera(d1=inner_d, d2=inner_d*2, h=taper_h, align=[0,0,1]);
                }
            }
        }

        cylindera(h=h+.2, d=inner_d, orient=[0,0,1], align=[0,0,0]);

    }
}

/*hollow_cylinder(thickness=2, h=9, taper=true, orient=[0,0,1], align=[0,0,1]);*/

/*%pie_slice(r=10, start_angle=-30, end_angle=270, h=10);*/

/*cubea([10,10,10],[1,0,0]);*/
/*%cubea([10,10,10],[1,0,0],[5,5,5],[1,1,1]);*/

/*%cubea([10,10,10],[-1,0,1]);*/
/*%cubea([10,10,10],[-1,0,1],[1,1,1],[-1,0,1]);*/
/*%cylindera(h=10, r=10/2, align=[-1,1,1], extra_r=5/2, extra_h=2, extra_align=[-1,1,1], $fn=100);*/

/*%cylindera(h=10, d=10, align=[-1,1,1], extra_d=5, extra_h=2, extra_align=[-1,1,1], $fn=100);*/
/*%cylindera(h=10, d=10, align=[1,1,1], extra_d=15, extra_h=2, extra_align=[1,1,1], $fn=100);*/

/*%cylindera(h=10, d=10, align=[1,-1,1], extra_d=5, extra_h=2, extra_align=[-1,-1,1], $fn=100);*/
/*%cylindera(h=10, d=10, align=[1,1,1], extra_d=5, extra_h=2, extra_align=[1,1,1], $fn=100);*/

/*%cylindera(h=10, d=10, align=[1,0,0], extra_d=10);*/

use <misc.scad>

// translate children
module lineup(arr=undef)
{
    /*echo(arr);*/
    /*echo($children);*/
    if($children>0)
    {
        for (i = [0 : $children-1])
            translate(arr[i]) children(i);
    }
}

module stack(separations)
{
    union()
    {
        for (i = [0:len(separations)-1])
        {
            offset = v_sum(separations,i);
            /*echo("i",i,"offset",offset);*/
            translate ([0,0,offset])
            {
                child(i);
            }
        }
    }
}

module orient(zaxes, roll=0)
{
    zaxes = len(zaxes.x) == undef && zaxes.x != undef? [zaxes] : zaxes;
    for(zaxis=zaxes)
    {
        rotate(_orient_angles(zaxis))
        /*rotate(roll*z)*/
            children();
    }
}

module size_align(size=[10,10,10], align=[0,0,0], orient=[0,0,1])
{
    bounds = _rotate_matrix(_orient_angles(orient)) * [size.x,size.y,size.z,1];
    t=hadamard(align, [abs(bounds.x/2),abs(bounds.y/2),abs(bounds.z/2)]);
    translate(t)
    {
        orient(orient)
        {
            children();
        }
    }
}

module cubea(size=[10,10,10], align=[0,0,0], extrasize=[0,0,0], extrasize_align=[0,0,0])
{
    size_align(extrasize,extrasize_align)
    {
        size_align(size,align)
        {
            cube(size+extrasize, center=true);
        }
    }
}

module cuberounda(size=[10,10,10], facets=32, rounding_radius=1, align=[0,0,0], extrasize=[0,0,0], extrasize_align=[0,0,0])
{
    size_align(extrasize,extrasize_align)
    {
        size_align(size,align)
        {
            cuberound(size=size+extrasize, facets=facets, rounding_radius=rounding_radius);
        }
    }
}

module cuberound(size=[20,20,20], rounding_radius=1)
{
    hull()
    for(x=[-(size[0]/2-rounding_radius),(size[0]/2-rounding_radius)])
    for(y=[-(size[1]/2-rounding_radius),(size[1]/2-rounding_radius)])
    for(z=[-(size[2]/2-rounding_radius),(size[2]/2-rounding_radius)])
    translate([x,y,z])
    sphere(r=rounding_radius);
}

module cylindera(
        h=10,
        r=undef,
        r1=undef,
        r2=undef,
        d=undef,
        d1=undef,
        d2=undef,
        align=[0,0,0],
        orient=[0,0,1],
        extra_h=0,
        extra_r=undef,
        extra_d=undef,
        extra_align=[0,0,1],
        debug=false
        )
{
    pi=3.1415926536;

    useDia = r == undef && (r1 == undef && r2 == undef);

    r1_ = useDia?((d1==undef?undef:d1)/2):r1;
    r2_ = useDia?((d2==undef?undef:d2)/2):r2;
    r_= useDia?d/2:(r==undef?0:r);
    r1r2max = max(r1,r2) == undef ? max(d1,d2)/2 : max(r1,r2);
    r__ = r_==undef? r1r2max : r_;
    extra_r_ = useDia?((extra_d==undef?0:extra_d)/2):((extra_r==undef)?0:extra_r);

    sizexy=r__*2;
    extra_sizexy=extra_r_*2;

    // some orient hax here to properly support extra_align
    orient(-orient)
    size_align([extra_sizexy,extra_sizexy,extra_h], align=extra_align, orient=orient)
    orient(orient)
    {
        if(debug)
        {
            echo(useDia, h, r_, r1_, r2_, extra_r_, align);
        }

        // some orient hax here to properly support extra_align
        orient(-orient)
        size_align([sizexy,sizexy,h], align=align, orient=orient)
        {
            cylinder(h=h+extra_h, r=r_+extra_r_, r1=r1_, r2=r2_, center=true);
        }
    }
}

module pie_slice_shape(r, start_angle, end_angle) {
    R = r * sqrt(2) + 1;
    a0 = (4 * start_angle + 0 * end_angle) / 4;
    a1 = (3 * start_angle + 1 * end_angle) / 4;
    a2 = (2 * start_angle + 2 * end_angle) / 4;
    a3 = (1 * start_angle + 3 * end_angle) / 4;
    a4 = (0 * start_angle + 4 * end_angle) / 4;
    if(end_angle > start_angle)
    {
        intersection() {
            circle(r);
            polygon([
                    [0,0],
                    [R * cos(a0), R * sin(a0)],
                    [R * cos(a1), R * sin(a1)],
                    [R * cos(a2), R * sin(a2)],
                    [R * cos(a3), R * sin(a3)],
                    [R * cos(a4), R * sin(a4)],
                    [0,0]
            ]);
        }
    }
}

module pie_slice(r, start_angle, end_angle, h)
{
    linear_extrude(h)
    {
        pie_slice_shape(r, start_angle, end_angle);
    }
}

module hollow_cylinder(d=10, thickness=1, h=10, taper=false, orient=[0,0,1], align=[0,0,0])
{
    outer_d = d+thickness/2;
    inner_d = d-thickness/2;
    size_align(size=[outer_d, outer_d, h], orient=orient, align=align)
    difference()
    {
        hull()
        {
            taper_h = outer_d/2;
            if(taper)
            {
                for(z=[-1,1])
                translate([0,0,z*h/2])
                mirror([0,0,z==-1?1:0])
                difference()
                {
                    cylindera(d1=outer_d, d2=0, h=taper_h, align=[0,0,1]);
                    cylindera(d1=inner_d, d2=inner_d*2, h=taper_h, align=[0,0,1]);
                }
            }
        }

        cylindera(h=h+.2, d=inner_d, orient=[0,0,1], align=[0,0,0]);

    }
}

/*hollow_cylinder(thickness=2, h=9, taper=true, orient=[0,0,1], align=[0,0,1]);*/

/*%pie_slice(r=10, start_angle=-30, end_angle=270, h=10);*/

/*cubea([10,10,10],[1,0,0]);*/
/*%cubea([10,10,10],[1,0,0],[5,5,5],[1,1,1]);*/

/*%cubea([10,10,10],[-1,0,1]);*/
/*%cubea([10,10,10],[-1,0,1],[1,1,1],[-1,0,1]);*/
/*%cylindera(h=10, r=10/2, align=[-1,1,1], extra_r=5/2, extra_h=2, extra_align=[-1,1,1], $fn=100);*/

/*%cylindera(h=10, d=10, align=[-1,1,1], extra_d=5, extra_h=2, extra_align=[-1,1,1], $fn=100);*/
/*%cylindera(h=10, d=10, align=[1,1,1], extra_d=15, extra_h=2, extra_align=[1,1,1], $fn=100);*/

/*%cylindera(h=10, d=10, align=[1,-1,1], extra_d=5, extra_h=2, extra_align=[-1,-1,1], $fn=100);*/
/*%cylindera(h=10, d=10, align=[1,1,1], extra_d=5, extra_h=2, extra_align=[1,1,1], $fn=100);*/

/*%cylindera(h=10, d=10, align=[1,0,0], extra_d=10);*/