added pentagon core for player

added pentagon core for player

$fn = 64;

// interference fit adjustment for 3D printer
iFitAdjust = .4;
iFitAdjust_d = .25;

// latch buttons
latchButtonDiameter = 13;
latchButtonHeight = 30;
module latch_button(color="green") {
    color(color)
        cylinder(h = latchButtonHeight, d = latchButtonDiameter, center = false);
}

// led momentary buttons
ledButtonDiameter = 25;
ledButtonHeight = 33;
module momentary_button(color="white") {
    color(color)
        cylinder(h = ledButtonHeight, d = ledButtonDiameter, center = false);
}

// encoders
encoderShaftDiameter = 8;
encoderShaftHeight = 18;
encoderShaftOffset = 9;
encoderWidth = 18;
encoderLength = 31;
encoderDepth = 8.2;
module encoder() {
    // encoder shaft
    cylinder(h = encoderShaftHeight, d = encoderShaftDiameter, center=false);
    // encoder base
    translate([-encoderWidth/2, -encoderShaftOffset, -encoderDepth/2])
        cube([encoderWidth, encoderLength, encoderDepth]);
}

// string
stringWallThickness = 1;
stringRecess = 5;
stringLength = 60;
photoresistorWidth = 5.5 + iFitAdjust_d;
photoresistorLength = photoresistorWidth;
photoresistorWireSep = 3.5;
ledLaserDiameter = 6.5 + iFitAdjust_d;
ledLaserLength = 10;
wireCasingDepth = 3;
stringWidth = ledLaserDiameter;
module photoresistor_holder() {
    difference() {
        cylinder(h = stringRecess + stringWallThickness * 2, d = 2 * stringWallThickness + photoresistorWidth + iFitAdjust_d, center = false);
        translate([0,0,-.1])
            cylinder(h = stringRecess + stringWallThickness * 2 + 1, d = photoresistorWidth + iFitAdjust_d, center = false);
        /*
        for (i = [-1,1])
            translate([i * photoresistorWireSep / 2, 0, -1])
                cylinder(h = 20, d = 1, center = false);
        */
    }
    rotate([0, 0, 180])
        translate([-(ledLaserDiameter + iFitAdjust_d + 2 * stringWallThickness)/2, -(ledLaserDiameter )/2 - 1, -(wireCasingDepth + stringWallThickness * 2)])
        difference() {
            cube([ledLaserDiameter + iFitAdjust_d + 2 * stringWallThickness, ledLaserDiameter + ledLaserDiameter / 2 + 1, wireCasingDepth + stringWallThickness * 2], center=false);
            translate([stringWallThickness, stringWallThickness * 2 + 1, stringWallThickness])
                cube([ledLaserDiameter + iFitAdjust_d , ledLaserDiameter + ledLaserDiameter / 2 - stringWallThickness, wireCasingDepth], center=false);
            translate([ledLaserDiameter / 2 + stringWallThickness, ledLaserDiameter / 2 + stringWallThickness, stringWallThickness])
                cylinder(h=wireCasingDepth + 2 * stringWallThickness, d = ledLaserDiameter + iFitAdjust, center=false);
        }
}
module led_holder() {
    difference() {
        cylinder(h = ledLaserLength + stringWallThickness * 2, d = 2 * stringWallThickness + ledLaserDiameter + iFitAdjust_d, center = false);
        translate([0,0,-.1])
            cylinder(h = ledLaserLength + stringWallThickness * 2 + 1, d = ledLaserDiameter + iFitAdjust_d, center = false);
        /*
        for (i = [-1,1])
            translate([i * photoresistorWireSep / 2, 0, -1])
                cylinder(h = 20, d = 1, center = false);
        */
    }
    translate([-(ledLaserDiameter + iFitAdjust_d + 2 * stringWallThickness)/2, -(ledLaserDiameter )/2 - 1, -(wireCasingDepth + stringWallThickness * 2)])
        difference() {
            cube([ledLaserDiameter + iFitAdjust_d + 2 * stringWallThickness, ledLaserDiameter + ledLaserDiameter / 2 + 1, wireCasingDepth + stringWallThickness * 2], center=false);
            translate([stringWallThickness, stringWallThickness * 2 + 1, stringWallThickness])
                cube([ledLaserDiameter + iFitAdjust_d , ledLaserDiameter + ledLaserDiameter / 2 - stringWallThickness, wireCasingDepth], center=false);
            translate([ledLaserDiameter / 2 + stringWallThickness, ledLaserDiameter / 2 + stringWallThickness, stringWallThickness])
                cylinder(h=wireCasingDepth + 2 * stringWallThickness, d = ledLaserDiameter + iFitAdjust, center=false);
        }
}
module string() {
 rotate([0, 0, 90])
  translate([0, -(wireCasingDepth + stringWallThickness * 2), ledLaserDiameter]) rotate([90, 0, 0])
   union() {
    photoresistor_holder();
    translate([0, 0, stringLength])
        rotate([180, 0, 0])
            led_holder();
    difference() {
        translate([-(ledLaserDiameter + 2 * stringWallThickness + iFitAdjust_d)/2, - ledLaserDiameter, 0])
            cube([ledLaserDiameter + iFitAdjust_d + 2 * stringWallThickness, ledLaserDiameter / 2, stringLength ], center = false);
        cylinder(h=100, d = ledLaserDiameter + iFitAdjust, center=false);
    }
   }
}

// display
    OLEDWidth = 27;
i2cOLEDHeight = 16;
i2cOLEDScrewWidth = 20;
i2cOLEDScrewHeight = 22;
module display() {
}

lidWidth = 100;
lidThickness = 2.5;
rowWidth = ledButtonDiameter + 10;
lidLength = rowWidth * 2 + ledButtonDiameter / 2;
controlOffset = 10;
lidScrewDiameter = 3.5;
lidScrewBoundaryOffset = 10;
module spoke_lid() {
    union() {
        difference () {
            cube([lidWidth, lidLength, lidThickness]);
            for (i = [0:1]) {
                translate([0, ledButtonDiameter + i * rowWidth, -lidThickness * 2]) {
            // led buttons
                    translate([ledButtonDiameter / 2 + controlOffset, 0, 0])
                        momentary_button();
            // encoders
                    translate([ledButtonDiameter / 2 + controlOffset + 2 * controlOffset + latchButtonDiameter / 2 + encoderLength / 4, 0, 0])
                    rotate([0, 0, 270])
                        encoder();
            // latch buttons
                    translate([ledButtonDiameter / 2 + controlOffset + 2 * controlOffset + latchButtonDiameter / 2 + encoderLength + 5, 0, 0])
                        latch_button();

                }
            }
            translate([lidScrewBoundaryOffset/2, lidScrewBoundaryOffset/2, -.1])
                cylinder(h=lidThickness * 2, d=lidScrewDiameter);
            translate([lidWidth - lidScrewBoundaryOffset/2, lidScrewBoundaryOffset/2, -.1])
                cylinder(h=lidThickness * 2, d=lidScrewDiameter);
            translate([lidScrewBoundaryOffset/2, lidLength - lidScrewBoundaryOffset/2, -.1])
                cylinder(h=lidThickness * 2, d=lidScrewDiameter);
            translate([lidWidth - lidScrewBoundaryOffset/2, lidLength - lidScrewBoundaryOffset/2, -.1])
                cylinder(h=lidThickness * 2, d=lidScrewDiameter);
        }
    }
}

module string_lid() {
    union() {
        difference () {
            union() {
                cube([lidWidth, lidLength, lidThickness]);
            }
            translate([lidScrewBoundaryOffset/2, lidScrewBoundaryOffset/2, -.1])
                cylinder(h=lidThickness * 2, d=lidScrewDiameter);
            translate([lidWidth - lidScrewBoundaryOffset/2, lidScrewBoundaryOffset/2, -.1])
                cylinder(h=lidThickness * 2, d=lidScrewDiameter);
            translate([lidScrewBoundaryOffset/2, lidLength - lidScrewBoundaryOffset/2, -.1])
                cylinder(h=lidThickness * 2, d=lidScrewDiameter);
            translate([lidWidth - lidScrewBoundaryOffset/2, lidLength - lidScrewBoundaryOffset/2, -.1])
                cylinder(h=lidThickness * 2, d=lidScrewDiameter);
            for (i = [0:7])
                translate([15 + stringWidth * i * 1.5, 5, -.01])
                    rotate([0, 0, 90])
                        hull() string();
        }
        for (i = [0:7])
            translate([15 + stringWidth * i * 1.5, 5, 0])
                rotate([0, 0, 90])
                    string();
   }
}

boxHeight = 45;
screwTabDim = 10;
boxThickness = lidThickness;
boxWidth = lidWidth;
boxLength = lidLength;
boxScrewDiameter = lidScrewDiameter;
module spoke_box() {
    difference() {
        union() {
             difference () {
                union() {
                    cube([lidWidth, lidLength, lidThickness]);
                    for (i = [0,1])
                        for (j = [0,1]) {
                            translate([i * lidWidth - i * screwTabDim, j * lidLength - j * screwTabDim, 0])
                                cube([screwTabDim, screwTabDim, boxHeight]);
                    }
                    cube([boxWidth, boxThickness, boxHeight]);
                    translate([0, boxLength - boxThickness, 0])
                        cube([boxWidth, boxThickness, boxHeight]);
                    cube([boxThickness, boxLength, boxHeight]);
                    translate([boxWidth - screwTabDim, 0, 0])
                        cube([screwTabDim, boxLength, screwTabDim]);
                }
                for (i = [0,1])
                    for (j = [0,1]) {
                        translate([i * boxWidth - i * screwTabDim + screwTabDim / 2, j * boxLength - j * screwTabDim + screwTabDim / 2, boxHeight - 9])
                            cylinder(h=20, d = lidScrewDiameter);
                    }
                for (i = [1, 2])
                    translate([boxWidth - screwTabDim / 2, i * boxLength / 3, boxThickness])
                        cylinder(h=screwTabDim + .1 - boxThickness, d=boxScrewDiameter);
                translate([boxWidth - screwTabDim / 2, screwTabDim + .1, (boxHeight / 3) * 2])
                    rotate([90, 0, 0])
                        cylinder(h=screwTabDim + .1 - boxThickness, d=boxScrewDiameter);
                translate([boxWidth - screwTabDim / 2, boxLength - boxThickness, (boxHeight / 3) * 2])
                    rotate([90, 0, 0])
                        cylinder(h=screwTabDim + .1 - boxThickness, d=boxScrewDiameter);
            }
        }
    }
}

pentagonRadius = boxLength / (2.0 * sin(180. / 5.));
pentagonR = (1/10) * sqrt(25 + 10 * sqrt(5)) * boxLength;
module pentagon_core() {
    difference() {
        union() {
            cylinder(h=boxThickness, r=pentagonRadius, $fn=5);
            translate([-pentagonR, 0, 0])
                    translate([0, -boxLength / 2, 0])
                        cube([screwTabDim, boxLength, screwTabDim]);
            rotate([0, 0,  36])
                translate([pentagonR - screwTabDim, 0, 0])
                    translate([0, -boxLength / 2, 0])
                        cube([screwTabDim, boxLength, screwTabDim]);
            rotate([0, 0,  2 * 36])
                translate([-pentagonR, 0, 0])
                    translate([0, -boxLength / 2, 0])
                        cube([screwTabDim, boxLength, screwTabDim]);
            rotate([0, 0,  3 * 36])
                translate([pentagonR - screwTabDim, 0, 0])
                    translate([0, -boxLength / 2, 0])
                        cube([screwTabDim, boxLength, screwTabDim]);
            rotate([0, 0,  4 * 36])
                translate([-pentagonR, 0, 0])
                    translate([0, -boxLength / 2, 0])
                        cube([screwTabDim, boxLength, screwTabDim]);
            for (i = [0:4])
                rotate([0, 0, i * 72])
                    for (j = [-1, 1])
                        translate([-pentagonR + screwTabDim / 2, j * boxLength / 2 - j * screwTabDim / 2, 0])
                            translate([0, 0, boxHeight/2])
                                cube([screwTabDim, screwTabDim, boxHeight], center=true);
        }
        for (i = [0:4])
            rotate([0, 0, i * 72])
                translate([-pentagonR + screwTabDim / 2, 0, 0]) {
                    translate([0, -boxLength / 3 / 2, boxThickness])
                        cylinder(h=screwTabDim + .1 - boxThickness, d=boxScrewDiameter);
                    translate([0, boxLength / 3 / 2, boxThickness])
                        cylinder(h=screwTabDim + .1 - boxThickness, d=boxScrewDiameter);
                }
        for (i = [0:4])
            rotate([0, 0, i * 72])
                for (j = [-1, 1])
                    translate([-pentagonR + screwTabDim / 2, j * boxLength / 2 - (j == -1 ? -1 * screwTabDim : screwTabDim / 4), 0])
                        translate([0, 0, (boxHeight / 3) * 2])
                            rotate([90, 0, 0])
                                #cylinder(h=screwTabDim + .1 - boxThickness, d=boxScrewDiameter);
         for (i = [0:4])
            rotate([0, 0, i * 72])
                translate([pentagonRadius - (screwTabDim / 3) * 2, 0, boxHeight - 9.9])
                    cylinder(h=10, d=boxScrewDiameter);
   }
}

module screw_tab() {
    difference() {
        cube([screwTabDim, 2 * screwTabDim, boxThickness]);
        for (i = [0,1])
            translate([screwTabDim / 2, screwTabDim / 2 + i * screwTabDim, -.1])
                cylinder(h=10, d=boxScrewDiameter);
    }
}

module case() {
    //spoke_lid();
    //string_lid();
    //spoke_box();
    //screw_tab();
    pentagon_core();
}

case();

$fn = 64;

// interference fit adjustment for 3D printer
iFitAdjust = .4;
iFitAdjust_d = .25;

// latch buttons
latchButtonDiameter = 13;
latchButtonHeight = 30;
module latch_button(color="green") {
    color(color)
        cylinder(h = latchButtonHeight, d = latchButtonDiameter, center = false);
}

// led momentary buttons
ledButtonDiameter = 24;
ledButtonHeight = 33;
module momentary_button(color="white") {
    color(color)
        cylinder(h = ledButtonHeight, d = ledButtonDiameter, center = false);
}

// encoders
encoderShaftDiameter = 7;
encoderShaftHeight = 18;
encoderShaftOffset = 9;
encoderWidth = 18;
encoderLength = 31;
encoderDepth = 8.2;
module encoder() {
    // encoder shaft
    cylinder(h = encoderShaftHeight, d = encoderShaftDiameter, center=false);
    // encoder base
    translate([-encoderWidth/2, -encoderShaftOffset, -encoderDepth/2])
        cube([encoderWidth, encoderLength, encoderDepth]);
}

// string
stringWallThickness = 1;
stringRecess = 5;
stringLength = 60;
photoresistorWidth = 5.5 + iFitAdjust_d;
photoresistorLength = photoresistorWidth;
photoresistorWireSep = 3.5;
ledLaserDiameter = 6.5 + iFitAdjust_d;
ledLaserLength = 10;
wireCasingDepth = 3;
stringWidth = ledLaserDiameter;
module photoresistor_holder() {
    difference() {
        cylinder(h = stringRecess + stringWallThickness * 2, d = 2 * stringWallThickness + photoresistorWidth + iFitAdjust_d, center = false);
        translate([0,0,-.1])
            cylinder(h = stringRecess + stringWallThickness * 2 + 1, d = photoresistorWidth + iFitAdjust_d, center = false);
        /*
        for (i = [-1,1])
            translate([i * photoresistorWireSep / 2, 0, -1])
                cylinder(h = 20, d = 1, center = false);
        */
    }
    rotate([0, 0, 180])
        translate([-(ledLaserDiameter + iFitAdjust_d + 2 * stringWallThickness)/2, -(ledLaserDiameter )/2 - 1, -(wireCasingDepth + stringWallThickness * 2)])
        difference() {
            cube([ledLaserDiameter + iFitAdjust_d + 2 * stringWallThickness, ledLaserDiameter + ledLaserDiameter / 2 + 1, wireCasingDepth + stringWallThickness * 2], center=false);
            translate([stringWallThickness, stringWallThickness * 2 + 1, stringWallThickness])
                cube([ledLaserDiameter + iFitAdjust_d , ledLaserDiameter + ledLaserDiameter / 2 - stringWallThickness, wireCasingDepth], center=false);
            translate([ledLaserDiameter / 2 + stringWallThickness, ledLaserDiameter / 2 + stringWallThickness, stringWallThickness])
                cylinder(h=wireCasingDepth + 2 * stringWallThickness, d = ledLaserDiameter + iFitAdjust, center=false);
        }
}
module led_holder() {
    difference() {
        cylinder(h = ledLaserLength + stringWallThickness * 2, d = 2 * stringWallThickness + ledLaserDiameter + iFitAdjust_d, center = false);
        translate([0,0,-.1])
            cylinder(h = ledLaserLength + stringWallThickness * 2 + 1, d = ledLaserDiameter + iFitAdjust_d, center = false);
        /*
        for (i = [-1,1])
            translate([i * photoresistorWireSep / 2, 0, -1])
                cylinder(h = 20, d = 1, center = false);
        */
    }
    translate([-(ledLaserDiameter + iFitAdjust_d + 2 * stringWallThickness)/2, -(ledLaserDiameter )/2 - 1, -(wireCasingDepth + stringWallThickness * 2)])
        difference() {
            cube([ledLaserDiameter + iFitAdjust_d + 2 * stringWallThickness, ledLaserDiameter + ledLaserDiameter / 2 + 1, wireCasingDepth + stringWallThickness * 2], center=false);
            translate([stringWallThickness, stringWallThickness * 2 + 1, stringWallThickness])
                cube([ledLaserDiameter + iFitAdjust_d , ledLaserDiameter + ledLaserDiameter / 2 - stringWallThickness, wireCasingDepth], center=false);
            translate([ledLaserDiameter / 2 + stringWallThickness, ledLaserDiameter / 2 + stringWallThickness, stringWallThickness])
                cylinder(h=wireCasingDepth + 2 * stringWallThickness, d = ledLaserDiameter + iFitAdjust, center=false);
        }
}
module string() {
 rotate([0, 0, 90])
  translate([0, -(wireCasingDepth + stringWallThickness * 2), ledLaserDiameter]) rotate([90, 0, 0])
   union() {
    photoresistor_holder();
    translate([0, 0, stringLength])
        rotate([180, 0, 0])
            led_holder();
    difference() {
        translate([-(ledLaserDiameter + 2 * stringWallThickness + iFitAdjust_d)/2, - ledLaserDiameter, 0])
            cube([ledLaserDiameter + iFitAdjust_d + 2 * stringWallThickness, ledLaserDiameter / 2, stringLength ], center = false);
        cylinder(h=100, d = ledLaserDiameter + iFitAdjust, center=false);
    }
   }
}

// display
    OLEDWidth = 27;
i2cOLEDHeight = 16;
i2cOLEDScrewWidth = 20;
i2cOLEDScrewHeight = 22;
module display() {
}

lidWidth = 100;
lidThickness = 2.5;
rowWidth = ledButtonDiameter + 10;
lidLength = rowWidth * 2 + ledButtonDiameter / 2;
controlOffset = 10;
lidScrewDiameter = 3.5;
lidScrewBoundaryOffset = 10;
module spoke_lid() {
    union() {
        difference () {
            cube([lidWidth, lidLength, lidThickness]);
            for (i = [0:1]) {
                translate([0, ledButtonDiameter + i * rowWidth, -lidThickness * 2]) {
            // led buttons
                    translate([ledButtonDiameter / 2 + controlOffset, 0, 0])
                        momentary_button();
            // encoders
                    translate([ledButtonDiameter / 2 + controlOffset + 2 * controlOffset + latchButtonDiameter / 2 + encoderLength / 4, 0, 0])
                    rotate([0, 0, 270])
                        encoder();
            // latch buttons
                    translate([ledButtonDiameter / 2 + controlOffset + 2 * controlOffset + latchButtonDiameter / 2 + encoderLength + 5, 0, 0])
                        latch_button();

                }
            }
            translate([lidScrewBoundaryOffset/2, lidScrewBoundaryOffset/2, -.1])
                cylinder(h=lidThickness * 2, d=lidScrewDiameter);
            translate([lidWidth - lidScrewBoundaryOffset/2, lidScrewBoundaryOffset/2, -.1])
                cylinder(h=lidThickness * 2, d=lidScrewDiameter);
            translate([lidScrewBoundaryOffset/2, lidLength - lidScrewBoundaryOffset/2, -.1])
                cylinder(h=lidThickness * 2, d=lidScrewDiameter);
            translate([lidWidth - lidScrewBoundaryOffset/2, lidLength - lidScrewBoundaryOffset/2, -.1])
                cylinder(h=lidThickness * 2, d=lidScrewDiameter);
        }
    }
}

module string_lid() {
    union() {
        difference () {
            union() {
                cube([lidWidth, lidLength, lidThickness]);
            }
            translate([lidScrewBoundaryOffset/2, lidScrewBoundaryOffset/2, -.1])
                cylinder(h=lidThickness * 2, d=lidScrewDiameter);
            translate([lidWidth - lidScrewBoundaryOffset/2, lidScrewBoundaryOffset/2, -.1])
                cylinder(h=lidThickness * 2, d=lidScrewDiameter);
            translate([lidScrewBoundaryOffset/2, lidLength - lidScrewBoundaryOffset/2, -.1])
                cylinder(h=lidThickness * 2, d=lidScrewDiameter);
            translate([lidWidth - lidScrewBoundaryOffset/2, lidLength - lidScrewBoundaryOffset/2, -.1])
                cylinder(h=lidThickness * 2, d=lidScrewDiameter);
            for (i = [0:7])
                translate([15 + stringWidth * i * 1.5, 5, -.01])
                    rotate([0, 0, 90])
                        hull() string();
        }
        for (i = [0:7])
            translate([15 + stringWidth * i * 1.5, 5, 0])
                rotate([0, 0, 90])
                    string();
   }
}

module case() {
    //spoke_lid();
    string_lid();
}

case();


for a demo

for a demo

$fn=100;
module round_cube(size_x, size_y, size_z, r) {
union() {
cube([size_x + 2*r, size_y, size_z], center=true);
cube([size_x , size_y + 2*r, size_z], center=true);
translate([-size_x/2, -size_y/2, 0]) cylinder(h=size_z, r=r, center=true);
translate([size_x/2, -size_y/2, 0]) cylinder(h=size_z, r=r, center=true);
translate([size_x/2, size_y/2, 0]) cylinder(h=size_z, r=r, center=true);
translate([-size_x/2, size_y/2, 0]) cylinder(h=size_z, r=r, center=true);
}

}

module gong_bang(all_x, side_x, mid_w, side_y, h) {
    cube([all_x, mid_w, h], center=true);
    translate([(all_x-side_x)/2, 0,0]) cube([side_x, side_y, h], center=true);
    translate([-(all_x-side_x)/2, 0,0]) cube([side_x, side_y, h], center=true);
    translate([-(all_x-side_x)/2, side_y/2,0])
    cylinder(r=side_x, h=h, center=true);
    translate([-(all_x-side_x)/2, -side_y/2,0])
    cylinder(r=side_x, h=h, center=true);
    translate([(all_x-side_x)/2, -side_y/2,0])
    cylinder(r=side_x, h=h, center=true);
    translate([(all_x-side_x)/2, side_y/2,0])
    cylinder(r=side_x, h=h, center=true);
}

shrink=0.1;
module gong_bang_shrink(all_x, side_x, mid_w, side_y, h) {
    gong_bang(all_x-shrink, side_x-shrink, mid_w-shrink,
        side_y-shrink, h);
}

//gong_bang(80, 2, 2, 10, 40);

out_x=46;
out_y=26;
all_z=20;
all_r=4;

lr_width=3;
f_width=3;
b_width=10;
bottom_h=3;

gb_x=out_x-2*all_r;
gb_sx=1;
gb_mw=2;
gb_sy=6;

top_z=bottom_h;

difference () {
round_cube(out_x,out_y,all_z,all_r);
translate([0,(f_width-b_width)/2,bottom_h]) round_cube(out_x-2*lr_width,out_y-f_width-b_width,all_z,all_r);
color([1,0,0])
translate([0, (out_y - b_width)/2 + all_r, 2])
gong_bang(gb_x, gb_sx, gb_mw, gb_sy, all_z);
translate([0, out_y/2, bottom_h])
    cube([gb_x-gb_sx-4, out_y, all_z], center=true);
}

//union() {
//round_cube(out_x,out_y,top_z,bottom_h);
translate([-100, 0,all_z])
union() {
round_cube(out_x,out_y,bottom_h,all_r);
    translate([0,0,bottom_h])
    difference() {
color([1,0,0])
translate([0,(f_width-b_width)/2,0]) round_cube(out_x-2*lr_width,out_y-f_width-b_width,bottom_h,all_r);
translate([0,(f_width-b_width)/2,1]) round_cube(out_x-4*lr_width,out_y-f_width-b_width-4,bottom_h,all_r);            }
color([0,0,1])
translate([0, (out_y - b_width)/2 + all_r, all_z/2-1])
gong_bang(gb_x, gb_sx, gb_mw, gb_sy, all_z);
//color([0,1,0])
//translate([0,(f_width-b_width)/2,-(top_z)]) round_cube(out_x-4*lr_width,out_y-f_width-b_width-10,bottom_h+1,all_r);
    }
//}

module round_cube(size_x, size_y, size_z, r) {
union() {
cube([size_x + 2*r, size_y, size_z], center=true);
cube([size_x , size_y + 2*r, size_z], center=true);
translate([-size_x/2, -size_y/2, 0]) cylinder(h=size_z, r=r, center=true);
translate([size_x/2, -size_y/2, 0]) cylinder(h=size_z, r=r, center=true);
translate([size_x/2, size_y/2, 0]) cylinder(h=size_z, r=r, center=true);
translate([-size_x/2, size_y/2, 0]) cylinder(h=size_z, r=r, center=true);
}

}

module gong_bang(all_x, side_x, mid_w, side_y, h) {
    cube([all_x, mid_w, h], center=true);
    translate([(all_x-side_x)/2, 0,0]) cube([side_x, side_y, h], center=true);
    translate([-(all_x-side_x)/2, 0,0]) cube([side_x, side_y, h], center=true);
}

gong_bang(80, 2, 2, 10, 40);

/*
color([0.5,0.5,0.99])
difference () {
round_cube(80+6,60+6,40,4);
translate([0,-2,3]) round_cube(80,58,40,4);
//translate([0,20,3]) round_cube(70,3,20,4);
translate([0,33.5,2]) cube([70,3,40],center=true);
}
*/


Added rim.

Added rim.

// OpenSCAD for a "mezzanine" extension for a Turtlebot3 burger
//           It includes a well for a breadboard and
//           rivet holes for a battery.
thickness = 4;
wide_y  = 26;    // The length of the wide rectangular portion
fillet_side= 16;    // End of flare to narrow
full_y  = 86;    // Greatest extent of the plate
wide_x  = 110;   // 1/2 width of the "wings"
narrow_x= 45;    // 1/2 width of the battery holder
breadboard_x = 52;  // Chopped
breadboard_y = 26;  // Chopped
breadboard_z = 10;
pillar_x     = 24;    // Center-line to center of pillar
pillar_y     = 30;    // Baseline to center of pillar
rim          = 3;     // Width of rim
rivet1_x     = 54;
rivet2_x     = 60;
rivet_y      = 8;
rivet_radius = 2.5;   // Hole radius for rivet attachment
round_radius = 2;     // Radius of the corner arcs

// 0,0 is upper left corner
module fillet(radius,angle) {
    rotate(angle,[0,0,1])
    difference() {
        square(radius,false);
        translate([radius,radius,0])
        circle(r=radius);
    }

}
// This is the basic plate. The baseline is y=0 along the GPIO pins.
// This object cannot be translated once created.
// y is negative towards us. Couldn't make a single hull work.
module base(z) {
    $fn=100;
    linear_extrude(height=z,center=false,convexity=10) {
        union() {
        hull() {
            // place 4 circles in the corners, with the rounding radius
            translate([-wide_x+round_radius/2, round_radius/2, 0])
            circle(r=round_radius);

            translate([wide_x-round_radius/2, round_radius/2, 0])
            circle(r=round_radius);

            translate([wide_x-round_radius/2, -wide_y+round_radius/2, 0])
            circle(r=round_radius);

            translate([-wide_x+round_radius/2, -wide_y+round_radius/2, 0])
            circle(r=round_radius);
            }
        };
        hull() {
            translate([narrow_x-round_radius/2, -wide_y+round_radius/2, 0])
            circle(r=round_radius);

            translate([narrow_x-round_radius/2, -full_y+round_radius/2, 0])
            circle(r=round_radius);

            translate([-narrow_x+round_radius/2, -full_y+round_radius/2, 0])
            circle(r=round_radius);

            translate([-narrow_x+round_radius/2, -wide_y+round_radius/2, 0])
            circle(r=round_radius);
        }
        translate([narrow_x,-wide_y,0])
        fillet(fillet_side,270);
        translate([-narrow_x,-wide_y,0])
        fillet(fillet_side,180);
    }
}

// This is the basic plate less a rim width all around. This is meant to
// be subtracted from the standard plate.
// There should be no rim where the hulls join
module base_cutout(z,rwidth) {
    $fn=100;
    linear_extrude(height=z,center=false,convexity=10) {
        union() {
        hull() {
            translate([-wide_x+round_radius/2+rwidth, round_radius/2-rwidth, 0])
            circle(r=round_radius);

            translate([wide_x-round_radius/2-rwidth, round_radius/2-rwidth, 0])
            circle(r=round_radius);

            translate([wide_x-round_radius/2-rwidth, -wide_y+round_radius/2+rwidth, 0])
            circle(r=round_radius);

            translate([-wide_x+round_radius/2+rwidth, -wide_y+round_radius/2+rwidth, 0])
            circle(r=round_radius);
            }
        };
        hull() {
            translate([narrow_x-round_radius/2-rwidth, -wide_y+round_radius/2, 0])
            circle(r=round_radius);

            translate([narrow_x-round_radius/2-rwidth, -full_y+round_radius/2+rwidth, 0])
            circle(r=round_radius);

            translate([-narrow_x+round_radius/2+rwidth,-full_y+round_radius/2+rwidth, 0])
            circle(r=round_radius);

            translate([-narrow_x+round_radius/2+rwidth, -wide_y+round_radius/2, 0])
            circle(r=round_radius);
        }
        translate([narrow_x-rwidth,-wide_y+rwidth,0])
        fillet(fillet_side,270);
        translate([-narrow_x+rwidth,-wide_y+rwidth,0])
        fillet(fillet_side,180);
    }
}

// --------------------- Final Assembly ----------------------
// Baseplate
translate([0,0,-thickness/2])
base(thickness);
translate([0,0,thickness/2])
difference() {
        base(thickness);
        base_cutout(thickness,rim);
  }

// OpenSCAD for a "mezzanine" extension for a Turtlebot3 burger
//           It includes a well for a breadboard and
//           rivet holes for a battery.
thickness = 4;
wide_y  = 26;    // The length of the wide rectangular portion
fillet_side= 16;    // End of flare to narrow
full_y  = 86;    // Greatest extent of the plate
wide_x  = 110;   // 1/2 width of the "wings"
narrow_x= 45;    // 1/2 width of the battery holder
breadboard_x = 52;  // Chopped
breadboard_y = 26;  // Chopped
breadboard_z = 10;
pillar_x     = 24;    // Center-line to center of pillar
pillar_y     = 30;    // Baseline to center of pillar
rim          = 3;     // Width of rim
rivet1_x     = 54;
rivet2_x     = 60;
rivet_y      = 8;
rivet_radius = 2.5;   // Hole radius for rivet attachment
round_radius = 2;     // Radius of the corner arcs

// 0,0 is upper left corner
module fillet(radius,angle) {
    rotate(angle,[0,0,1])
    difference() {
        square(radius,false);
        translate([radius,radius,0])
        circle(r=radius);
    }

}
// This is the basic plate. The baseline is y=0 along the GPIO pins.
// This object cannot be translated once created.
// y is negative towards us. Couldn't make a single hull work.
module base(z) {
    $fn=100;
    linear_extrude(height=z,center=false,convexity=10) {
        union() {
        hull() {
            // place 8 circles in the corners, with the rounding radius
            translate([-wide_x+round_radius/2, round_radius/2, 0])
            circle(r=round_radius);

            translate([wide_x-round_radius/2, round_radius/2, 0])
            circle(r=round_radius);

            translate([wide_x-round_radius/2, -wide_y+round_radius/2, 0])
            circle(r=round_radius);

            translate([-wide_x+round_radius/2, -wide_y+round_radius/2, 0])
            circle(r=round_radius);
            }
        };
        hull() {
            translate([narrow_x-round_radius/2, -wide_y+round_radius/2, 0])
            circle(r=round_radius);

            translate([narrow_x-round_radius/2, -full_y+round_radius/2, 0])
            circle(r=round_radius);

            translate([-narrow_x+round_radius/2, -full_y+round_radius/2, 0])
            circle(r=round_radius);

            translate([-narrow_x+round_radius/2, -wide_y+round_radius/2, 0])
            circle(r=round_radius);
        }
        translate([narrow_x,-wide_y,0])
        fillet(fillet_side,270);
        translate([-narrow_x,-wide_y,0])
        fillet(fillet_side,180);
    }
}

// This is the basic plate less a rim width all around. This is meant to
// be subtracted from the standard plate.
module base_cutout(z,rwidth) {
    $fn=100;
    linear_extrude(height=z,center=false,convexity=10) {
        union() {
        hull() {
            // place 8 circles in the corners, with the rounding radius
            translate([-wide_x+round_radius/2, round_radius/2, 0])
            circle(r=round_radius);

            translate([wide_x-round_radius/2, round_radius/2, 0])
            circle(r=round_radius);

            translate([wide_x-round_radius/2, -wide_y+round_radius/2, 0])
            circle(r=round_radius);

            translate([-wide_x+round_radius/2, -wide_y+round_radius/2, 0])
            circle(r=round_radius);
            }
        };
        hull() {
            translate([narrow_x-round_radius/2, -wide_y+round_radius/2, 0])
            circle(r=round_radius);

            translate([narrow_x-round_radius/2, -full_y+round_radius/2, 0])
            circle(r=round_radius);

            translate([-narrow_x+round_radius/2, -full_y+round_radius/2, 0])
            circle(r=round_radius);

            translate([-narrow_x+round_radius/2, -wide_y+round_radius/2, 0])
            circle(r=round_radius);
        }
    }
}

// --------------------- Final Assembly ----------------------
// Baseplate
translate([0,0,-thickness/2])
base(thickness);
translate([0,0,thickness/2])
difference() {
        base(thickness);
        base_cutout(thickness,rim);
  }


Añadidas casillas finales

Añadidas casillas finales

module arandela(interior,total,altura)
{
		difference() {
			cylinder(h= altura, r=total,$fa=1,$fs=0.1);
			translate([0,0,-1]){
				cylinder(h=altura+2, r=interior,$fa=1,$fs=0.1);
			}
		}
}

module base(alto,ancho,largo,anc){
	difference() {
		cylinder(h=alto, r=ancho+largo,$fa=1,$fs=0.1);
		translate([0,0,-1]){
			difference() {
				cylinder(h=alto-anc, r=ancho+largo+1,$fa=1,$fs=0.1);
				translate([0,0,-1]){
					cylinder(h=alto-anc+2, r=ancho,$fa=1,$fs=0.1);
				}
			}
		}
	}
}

module led(ancho1, profundo1, ancho2){
translate([0,0,ha+1]){
rotate([180,0,0]){
	cylinder(h=profundo1, r=ancho1,$fa=1,$fs=0.1);
	difference(){
		hull(){
		translate([ancho1/2,0,0]){
		cylinder(h=ha+2,r=ancho2,$fa=1,$fs=0.1);
		}
		translate([-(ancho1/2),0,0]){
		cylinder(h=ha+2,r=ancho2,$fa=1,$fs=0.1);
		}}
		cube(size = [1,2,ha+100], center = true);
	}
}}
}

module toSubstract(){
		arandela(8.5,15.4,3.9);
		arandela(3.5,7,2.2);
}

module base_arandelas(a,ab,b){

translate([0,0,ha+0.1]){
rotate([180,0,0]){
difference(){

translate([0,0,ha+0.1]){
rotate([180,0,0]){
		base(ha,a,ab,b);
}
}
		toSubstract();
	}
}}}

module cable(dist){
translate([dist,0,-3]){
cylinder(h=ha, r=1,$fa=1,$fs=0.1);
translate([0,0,ha]){
sphere(2, $fa=1, $fs=0.1);
}
}
}

module cable2(dist){
translate([-dist,0,-1.5]){
cylinder(h=ha, r=1,$fa=1,$fs=0.1);
translate([0,0,ha]){
sphere(1.5, $fa=1, $fs=0.1);
}
}
}

ha=20;
a=17;
ab=2;
b=1;

difference(){
base_arandelas(a,ab,b);
led(3.1,8,1);
cable(12.25);
cable2(5.25);
}

error: pathspec 'modelos/casilla.scad' did not match any file(s) known to git


misc: add array_header_col_{add,subtract}

include <system.scad>
use <scad-utils/linalg.scad>
use <scad-utils/lists.scad>

function posvec(path_vec) = [for(v=path_vec) translation_part(v)];
function posvec_x(path_vec) = [for(v=path_vec) translation_part(v)[0]];
function posvec_y(path_vec) = [for(v=path_vec) translation_part(v)[1]];
function posvec_z(path_vec) = [for(v=path_vec) translation_part(v)[2]];

function vec_i(v3,i) = [for(v=v3) v[i]];
function vec_0(v3) = vec_i(v3,0);
function vec_1(v3) = vec_i(v3,1);
function vec_2(v3) = vec_i(v3,2);

// if V is array and len == 1, return single value, otherwise return V
function singlify(V) = len(V)==1?V[0]:V;
if($test_mode)
{
    assert_v(singlify("t"),"t");
    assert_v(singlify("test"),"test");
    assert_v(singlify(0),0);
    assert_v(singlify([]),[]);
    assert_v(singlify([0]),0);
    assert_v(singlify([0,1]),[0,1]);
}

function v_itrlen(vec) = [0:1:len(vec)-1];

function range1(v1) = [min(v1), max(v1)];
function range3(v3) = [range1(vec_0(v3)), range1(vec_1(v3)), range1(vec_2(v3))];
function bbox(r) = [ [r[0][0],r[1][0],r[2][0]], [r[0][1],r[1][1],r[2][1]] ];
function transform_pp(vec_m, t_pre, t_post) = [for(m=vec_m) (t_pre*m)*t_post];
function transform_pre(vec_m, t) = [for(m=vec_m) t*m];
function transform_post(vec_m, t) = [for(m=vec_m) m*t];

function clamp(v, v1, v2) = min(max(v,v1),v2);

// from the start (or s'th element) to the e'th element - remember elements are zero based
function v_sum(v,e=U,start=0) =
let(e_= fallback(e, len(v)-1))
(e==start ? v[e] : v[e_] + v_sum(v,e_-1,start));

function get(key, dict) =
    let(x = search(key, dict))
    let(kv = dict[x[0]])
    kv[1];

function v_i(vec,i) = [for(vv=vec) vv[i]];
function v_get(vec,key) = [for(vv=vec) get(key, vv)];
function v_add(vec,v) = [for(vv=vec) vv+v];
function v_sub(vec,v) = [for(vv=vec) vv+v];
function v_avg(v,e=U,start=0) = v_sum(v,e,start) / (len(v));
function v_abs(v, start=0) = [for(i=[start:1:len(v)-1]) abs(v[i])];
function v_sign(v, start=0) = [for(i=[start:1:len(v)-1]) sign(v[i])];
function v_max(v, m, start=0) = [for(i=[start:1:len(v)-1]) max(v[i],m)];
function v_min(v, m, start=0) = [for(i=[start:1:len(v)-1]) min(v[i],m)];
function v_clamp(v, v1, v2, start=0) = [for(i=[start:1:len(v)-1]) clamp(v[i],v1,v2)];

function v_slice(v, start, end) =
let(start_ = start==U?0:start)
let(end_ = end==U?len(v)-1:end)
[for(i=[start_:1:end_]) v[i]];

if($test_mode)
{
    v=[0,1,2];
    assert_v(v_slice(v), [0, 1,2]);
    assert_v(v_slice(v,start=1), [1,2]);
    assert_v(v_slice(v,end=1), [0, 1]);
    assert_v(v_slice(v,start=1,end=1), [1]);
}

// cumulative sum of vector [1,2,3] = [1,3,6]
function v_cumsum(v, start=0, end) = [for(i=[start:1:end==U?len(v)-1:end]) v_sum(v,i)];

// filter/remove a val from a vec
function filter(vec,val=U) = [for(v=vec) if(v!=val) v];

function vec_pair_double_transform_post(vec,t1,t2)=
    flatten(
        [for(v=vec)
            [transform_post(v,t1),transform_post(v,t2)]
        ]);

function vec_pair_double(vec)=flatten([for(v=vec) [v,v] ]);

/** Calculates length of hypotenuse according to pythagoras */
function pythag_hyp(a, b)=sqrt(a*a+b*b);
function pythag_leg(b, c)=sqrt(c*c-b*b);

function v_x(v) = [v[0],0,0];
function v_y(v) = [0,v[1],0];
function v_z(v) = [0,0,v[2]];

function v_xy(v) = [v[0],v[1],0];
function v_xyz(v) = [v[0],v[1],v[2]];
function v_yz(v) = [0,v[1],v[2]];
function v_z(v) = [0,0,v[2]];

//-- Calculate the module/magnitude of a vector
function v_mod(v) = (sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]));

//-- Calculate the cross product of two vectors
function v_cross(u,v) = [
  u[1]*v[2] - v[1]*u[2],
  u[2]*v[0] - v[2]*u[0],
  u[0]*v[1] - v[0]*u[1]
];

//-- Calculate the dot product of two vectors
function v_dot(u,v) = u[0]*v[0]+u[1]*v[1]+u[2]*v[2];

//-- Return the unit vector of a vector
function v_unitv(v) = v/v_mod(v);

//-- Return the angle between two vectores
function v_anglev(u,v) = acos( v_dot(u,v) / (v_mod(u)*v_mod(v)) );

function _orient_angles(zaxis)=
[
    -asin(zaxis.y / norm(zaxis)),
    atan2(zaxis.x, zaxis.z),
    0
];

/*function _orient_angles_(v)=*/
/*[*/
    /*-atan2(sqrt(v.x*v.x+v.y*v.y), v.z),*/
    /*0,*/
    /*-atan2(v.x, v.z)*/
/*];*/

//matrix rotation functions
function _rotate_x_matrix(a)=
[[1,0,0,0],
    [0,cos(a),-sin(a),0],
    [0,sin(a),cos(a),0],
    [0,0,0,1]];

function _rotate_y_matrix(a)=
[[cos(a),0,sin(a),0],
    [0,1,0,0],
    [-sin(a),0,cos(a),0],
    [0,0,0,1]];

function _rotate_z_matrix(a)=
[[cos(a),-sin(a),0,0],
    [sin(a),cos(a),0,0],
    [0,0,1,0],
    [0,0,0,1]];

function _rotate_matrix(a)=_rotate_z_matrix(a.z)*_rotate_y_matrix(a.y)*_rotate_x_matrix(a.x);

//hadamard product (aka "component-wise" product) for vectors
function hadamard(v1,v2) = [v1.x*v2.x, v1.y*v2.y, v1.z*v2.z];

// search in a dictionary (vector w/key-value pairs) and replace the value for a given key
function dict_replace(dict, key, newvalue)=[
        for(kv=dict)
        kv[0] == key ?
            [key, newvalue]
            :
            kv
        ];

function dict_replace_multiple(dict, newvaluesdict)=[
    for(kv_old=dict)
    let(r = search(kv_old[0], newvaluesdict, num_returns_per_match=0, index_col_num=0))
    r==[]?kv_old:newvaluesdict[r[0]]
    ];

function sinh(x) = (1 - pow(e, -2 * x)) / (2 * pow(e, -x));
function cosh(x) = (1 + pow(e, -2 * x)) / (2 * pow(e, -x));
function tanh(x) = sinh(x) / cosh(x);
function cot(x) = 1 / tan(x);

function factorial(n) = n == 0 ? 1 : factorial(n - 1) * n;

if(false)
{
    vec=[ 10, 20, 30, 40 ];
    echo("v_sum=", v_sum(vec,2,1)); // is 20+30=50
    echo("v_sum=", v_sum(vec));
    echo("v_cumsum=", v_cumsum(vec));
}

// FUNCTION: is_String(x)
//   Returns true if x is a string, false otherwise.
function is_string(x) =
	x == U || len(x) == U
		? false // if U, a boolean or a number
		: len(str(x,x)) == len(x)*2; // if an array, this is false

// FUNCTION: is_array(x)
//   Returns true if x is an array, false otherwise.
function is_array(x) = is_string(x) ? false : len(x) != U;

function identity(d)        = d == 0 ? 1 : [for(y=[1:d]) [for(x=[1:d]) x == y ? 1 : 0] ];
function unit_vector(v)     = let(x=v[0], y=v[1], z=v[2]) [x/norm(v), y/norm(v), z/norm(v)];
function skew_symmetric(v)  = let(x=v[0], y=v[1], z=v[2]) [[0, -z, y], [z, 0, -x], [-y, x, 0]];
function tensor_product1(u) = let(x=u[0], y=u[1], z=u[2]) [[x*x, x*y, x*z], [x*y, y*y, y*z], [x*z, y*z, z*z]];
function v_rotate(a, v)
    = is_array(a)
? let(rx=a[0], ry=a[1], rz=a[2])
    [[1, 0, 0],              [0, cos(rx), -sin(rx)], [0, sin(rx), cos(rx)]]
  * [[cos(ry), 0, sin(ry)],  [0, 1, 0],              [-sin(ry), 0, cos(ry)]]
  * [[cos(rz), -sin(rz), 0], [sin(rz), cos(rz), 0],  [0, 0, 1]]
    : let(uv=unit_vector(v))
    cos(a)*identity(3) + sin(a)*skew_symmetric(uv) + (1 - cos(a))*tensor_product1(uv);

 /*echo(rotate(90, X) * [1, 0, 0]);*/
 /*echo(rotate(90, X) * [0, 1, 0]);*/
 /*echo(rotate(90, X) * [0, 0, 1]);*/

function lerp(v0, v1, t) =  (1-t)*v0 + t*v1;

if($test_mode)
{
    assert(lerp(-1, 1, 0) == -1);
    assert(lerp1(-1, 1, .5) == 0);
    assert(lerp1(-1, 1, 1) == 1);
}

if($test_mode)
{
    assert_v(fallback(U,1), 1);
}

function fallback(a, b) = a==U?b:a;

// echo(fallback(U,[U, 1]));
function v_fallback(a,v,i=0) = (a!=U || i > len(v)-1) ? a : v_fallback(v[i],v,i+1);

function zip(a,b,start=0,end) = [for(i=[start:1:fallback(end,len(a)-1)]) [a[i],b[i]] ];
function zip_v(v,start=0,end) = [for(i=[start:1:fallback(end,len(v[0])-1)]) v_i(v,i) ];

if($test_mode)
{
    vec_a = [0,4];
    vec_b = [1,5];
    vec_c = [2,6];
    vec_d = [3,7];
    assert_v(zip(vec_a,vec_b),[[0,1],[4,5]]);
    assert_v(zip_v([vec_a,vec_b]),[[0,1],[4,5]]);
    assert_v(zip_v([vec_a,vec_b,vec_c,vec_d]), [[0,1,2,3],[4,5,6,7]]);
}

function vv_fallback(v,start=0,end) =
let(z = zip_v(v))
[
for(i=[start:1:fallback(end,len(v[0])-1)])
    v_fallback(v=z[i],i=0)
];

if($test_mode)
{
    vec_a=[ 10,  U,   U, 40 ];
    vec_b=[ 10,  U,  30,  U ];
    vec_c=[  U, 20,   U, 40 ];
    assert(v_fallback(a=5, v=vec_a), 5);
    assert_v(vv_fallback(v=[vec_a, vec_b,vec_c]), [10,20,30,40]);
}

function fn_from_r(r) =
                    $fn > 0.0 ?
                    ($fn >= 3 ? $fn : 3)
                    :
                    ceil(max(min(360.0 / $fa, r*2*PI / $fs), 5));

function fn_from_d(d) =
                    $fn > 0.0 ?
                    ($fn >= 3 ? $fn : 3)
                    :
                    ceil(max(min(360.0 / $fa, d*PI / $fs), 5));

module assert_v(val, expected, message)
{
    if(len(val) > 0)
    {
        if(len(val) != len(expected))
        {
            echo("assertion, not equal length of arrays", val, expected);
            assert(val == expected, message);
        }
        for(i=[0:len(val)])
        {
            if(val[i] != expected[i])
            {
                echo("assertion, unexpected value at index", i, val, expected);
                assert(val == expected, message);
            }
        }

    }
    else
    {
        if(val != expected)
        {
            echo("assertion, unexpected value", val, expected);
            assert(val == expected, message);
        }
    }
}

function spread(v0,v1,a) =
a>=2 ?
    [for(i=[0:1/(a-1):1]) lerp(v0,v1,i)]
:
    [lerp(v0,v1,.5)]
;

if($test_mode)
{
    assert_v(spread(-1, 1, 1), [0]);
    assert_v(spread(-1, 1, 2), [-1,1]);
    assert_v(spread(-1, 1, 3), [-1,0,1]);
    // fails because of float inaccuracy
    /*assert_v(spread(-1, 1, 4), [-1,-1/3,1/3,1]);*/
    assert_v(spread(-1, 1, 5), [-1,-.5,0,.5,1]);
}

// the apothem (inradius) is the distance from the center of a regular
// polygon to the flat side (not a vertex)
function apothem(circumradius, fn) = circumradius*cos(180/fn);
function inradius(circumradius, fn) = circumradius*cos(180/fn);;
// the circumradius (outradius) is the distance from the center of a regular
// polygon to a vertex
function circumradius(apothem, fn) = apothem / cos(180/fn);
function outradius(apothem, fn) = apothem / cos(180/fn);
function fn_radius(r, fn) = apothem(r,fn);
function hex_radius(r) = apothem(r, 6);

if($test_mode)
{
    assert_v(apothem(circumradius(5,6)), circumradius(apothem(5),6));
}

function header_col_index(v, col_keys) =
    singlify(
        [for(col_key=col_keys)
        let(result=search([col_key], v[0], index_col_number=0, num_returns_per_match=0))
        result[0][0]
        ]
    );

function geth(S, col_keys, row_index) =
    singlify(
        [for(col_key=col_keys)
            let(col_index = header_col_index(S, col_key))
            S[row_index+1][col_index]
        ]);

if($test_mode)
{
    A = [
    ["Tx", "Ty"],
    [1, 2],
    [3, 4],
    ];

    assert_v(header_col_index(A, "Tx"), 0);
    assert_v(header_col_index(A, "Ty"), 1);

    assert_v(header_col_index(A, ["Ty"]), 1);
    assert_v(header_col_index(A, ["Tx"]), 0);
    assert_v(header_col_index(A, ["Tx", "Ty"]), [0,1]);

    assert_v(geth(A, "Tx", 0), 1);
    assert_v(geth(A, "Tx", 1), 3);
    assert_v(geth(A, "Ty", 0), 2);
    assert_v(geth(A, "Ty", 1), 4);

    assert_v(geth(A, ["Tx","Ty"], 0), [1,2]);
    assert_v(geth(A, ["Tx","Ty"], 1), [3,4]);

}

function v_contains(V, val, start=0, end=U) =
    !is_array(V) ?
        V == val :
        let(e=end==U?len(V):end)
        V[start]==val ? true :
        start == len(V)-1 ? false :
        v_contains(V,val,start+1,end);

if($test_mode)
{
    assert_v(v_contains(0, 0), true);
    assert_v(v_contains(0, 1), false);
    assert_v(v_contains([0,1], 0), true);
    assert_v(v_contains([0,1], 1), true);
    assert_v(v_contains([0,1], 2), false);
}

// helper functions to work on headered-arrays (where first entry is column headers)
function reverse_header(V) = concat([V[0]], reverse(v_slice(V,start=1)));
function concat_header(A,B) =concat([A[0]], v_slice(A,start=1),v_slice(B,start=1));

// add value from these columns in headered array
function array_header_col_add(S, cols, val) =
    let(cols = header_col_index(S,cols))
    concat([S[0]],
    [
        for(i=[1:len(S)-1])
        [
        for(j=[0:len(S[0])-1])
            (v_contains(cols,j)) ?
                S[i][j] + val :
                S[i][j]
        ]
    ]);

function array_header_col_subtract(S, cols, val) = array_header_col_add(S,cols,-val);

if($test_mode)
{
    A = [
    ["Tx", "Ty"],
    [1, 2],
    [3, 4],
    ];

    assert_v(
        array_header_col_add(A, "Tx", -1),
        [["Tx","Ty"],
         [0,2],
         [2,4],
        ]);

    assert_v(
        array_header_col_add(A, ["Tx"], -1),
        [["Tx","Ty"],
         [0,2],
         [2,4],
        ]);

    assert_v(
        array_header_col_add(A, ["Tx","Ty"], -1),
        [["Tx","Ty"],
         [0,1],
         [2,3],
        ]);

    assert_v(
        array_header_col_add(A, ["Ty"], -1),
        [["Tx","Ty"],
         [1,1],
         [3,3],
        ]);
}

function take3(v) = [v[0],v[1],v[2]];

function vec3(V) =
let(l = len(V))
l == 3 ? V :
l < 3 ? vec3(concat(V,0)) :
take3(V);

if($test_mode)
{
    assert_v(take3([0,1,0,1]), [0,1,0]);

    assert_v(vec3([0,1]), [0,1,0]);
    assert_v(vec3([0]), [0,0,0]);
    assert_v(vec3([1]), [1,0,0]);
    assert_v(vec3([0,0,1]), [0,0,1]);
    assert_v(vec3([0,0,1,0]), [0,0,1]);
}

include <system.scad>
use <scad-utils/linalg.scad>
use <scad-utils/lists.scad>

function posvec(path_vec) = [for(v=path_vec) translation_part(v)];
function posvec_x(path_vec) = [for(v=path_vec) translation_part(v)[0]];
function posvec_y(path_vec) = [for(v=path_vec) translation_part(v)[1]];
function posvec_z(path_vec) = [for(v=path_vec) translation_part(v)[2]];

function vec_i(v3,i) = [for(v=v3) v[i]];
function vec_0(v3) = vec_i(v3,0);
function vec_1(v3) = vec_i(v3,1);
function vec_2(v3) = vec_i(v3,2);

// if V is array and len == 1, return single value, otherwise return V
function singlify(V) = len(V)==1?V[0]:V;
if($test_mode)
{
    assert_v(singlify("t"),"t");
    assert_v(singlify("test"),"test");
    assert_v(singlify(0),0);
    assert_v(singlify([]),[]);
    assert_v(singlify([0]),0);
    assert_v(singlify([0,1]),[0,1]);
}

function v_itrlen(vec) = [0:1:len(vec)-1];

function range1(v1) = [min(v1), max(v1)];
function range3(v3) = [range1(vec_0(v3)), range1(vec_1(v3)), range1(vec_2(v3))];
function bbox(r) = [ [r[0][0],r[1][0],r[2][0]], [r[0][1],r[1][1],r[2][1]] ];
function transform_pp(vec_m, t_pre, t_post) = [for(m=vec_m) (t_pre*m)*t_post];
function transform_pre(vec_m, t) = [for(m=vec_m) t*m];
function transform_post(vec_m, t) = [for(m=vec_m) m*t];

function clamp(v, v1, v2) = min(max(v,v1),v2);

// from the start (or s'th element) to the e'th element - remember elements are zero based
function v_sum(v,e=U,start=0) =
let(e_= fallback(e, len(v)-1))
(e==start ? v[e] : v[e_] + v_sum(v,e_-1,start));

function get(key, dict) =
    let(x = search(key, dict))
    let(kv = dict[x[0]])
    kv[1];

function v_i(vec,i) = [for(vv=vec) vv[i]];
function v_get(vec,key) = [for(vv=vec) get(key, vv)];
function v_add(vec,v) = [for(vv=vec) vv+v];
function v_sub(vec,v) = [for(vv=vec) vv+v];
function v_avg(v,e=U,start=0) = v_sum(v,e,start) / (len(v));
function v_abs(v, start=0) = [for(i=[start:1:len(v)-1]) abs(v[i])];
function v_sign(v, start=0) = [for(i=[start:1:len(v)-1]) sign(v[i])];
function v_max(v, m, start=0) = [for(i=[start:1:len(v)-1]) max(v[i],m)];
function v_min(v, m, start=0) = [for(i=[start:1:len(v)-1]) min(v[i],m)];
function v_clamp(v, v1, v2, start=0) = [for(i=[start:1:len(v)-1]) clamp(v[i],v1,v2)];

function v_slice(v, start, end) =
let(start_ = start==U?0:start)
let(end_ = end==U?len(v)-1:end)
[for(i=[start_:1:end_]) v[i]];

if($test_mode)
{
    v=[0,1,2];
    assert_v(v_slice(v), [0, 1,2]);
    assert_v(v_slice(v,start=1), [1,2]);
    assert_v(v_slice(v,end=1), [0, 1]);
    assert_v(v_slice(v,start=1,end=1), [1]);
}

// cumulative sum of vector [1,2,3] = [1,3,6]
function v_cumsum(v, start=0, end) = [for(i=[start:1:end==U?len(v)-1:end]) v_sum(v,i)];

// filter/remove a val from a vec
function filter(vec,val=U) = [for(v=vec) if(v!=val) v];

function vec_pair_double_transform_post(vec,t1,t2)=
    flatten(
        [for(v=vec)
            [transform_post(v,t1),transform_post(v,t2)]
        ]);

function vec_pair_double(vec)=flatten([for(v=vec) [v,v] ]);

/** Calculates length of hypotenuse according to pythagoras */
function pythag_hyp(a, b)=sqrt(a*a+b*b);
function pythag_leg(b, c)=sqrt(c*c-b*b);

function v_x(v) = [v[0],0,0];
function v_y(v) = [0,v[1],0];
function v_z(v) = [0,0,v[2]];

function v_xy(v) = [v[0],v[1],0];
function v_xyz(v) = [v[0],v[1],v[2]];
function v_yz(v) = [0,v[1],v[2]];
function v_z(v) = [0,0,v[2]];

//-- Calculate the module/magnitude of a vector
function v_mod(v) = (sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]));

//-- Calculate the cross product of two vectors
function v_cross(u,v) = [
  u[1]*v[2] - v[1]*u[2],
  u[2]*v[0] - v[2]*u[0],
  u[0]*v[1] - v[0]*u[1]
];

//-- Calculate the dot product of two vectors
function v_dot(u,v) = u[0]*v[0]+u[1]*v[1]+u[2]*v[2];

//-- Return the unit vector of a vector
function v_unitv(v) = v/v_mod(v);

//-- Return the angle between two vectores
function v_anglev(u,v) = acos( v_dot(u,v) / (v_mod(u)*v_mod(v)) );

function _orient_angles(zaxis)=
[
    -asin(zaxis.y / norm(zaxis)),
    atan2(zaxis.x, zaxis.z),
    0
];

/*function _orient_angles_(v)=*/
/*[*/
    /*-atan2(sqrt(v.x*v.x+v.y*v.y), v.z),*/
    /*0,*/
    /*-atan2(v.x, v.z)*/
/*];*/

//matrix rotation functions
function _rotate_x_matrix(a)=
[[1,0,0,0],
    [0,cos(a),-sin(a),0],
    [0,sin(a),cos(a),0],
    [0,0,0,1]];

function _rotate_y_matrix(a)=
[[cos(a),0,sin(a),0],
    [0,1,0,0],
    [-sin(a),0,cos(a),0],
    [0,0,0,1]];

function _rotate_z_matrix(a)=
[[cos(a),-sin(a),0,0],
    [sin(a),cos(a),0,0],
    [0,0,1,0],
    [0,0,0,1]];

function _rotate_matrix(a)=_rotate_z_matrix(a.z)*_rotate_y_matrix(a.y)*_rotate_x_matrix(a.x);

//hadamard product (aka "component-wise" product) for vectors
function hadamard(v1,v2) = [v1.x*v2.x, v1.y*v2.y, v1.z*v2.z];

// search in a dictionary (vector w/key-value pairs) and replace the value for a given key
function dict_replace(dict, key, newvalue)=[
        for(kv=dict)
        kv[0] == key ?
            [key, newvalue]
            :
            kv
        ];

function dict_replace_multiple(dict, newvaluesdict)=[
    for(kv_old=dict)
    let(r = search(kv_old[0], newvaluesdict, num_returns_per_match=0, index_col_num=0))
    r==[]?kv_old:newvaluesdict[r[0]]
    ];

function sinh(x) = (1 - pow(e, -2 * x)) / (2 * pow(e, -x));
function cosh(x) = (1 + pow(e, -2 * x)) / (2 * pow(e, -x));
function tanh(x) = sinh(x) / cosh(x);
function cot(x) = 1 / tan(x);

function factorial(n) = n == 0 ? 1 : factorial(n - 1) * n;

if(false)
{
    vec=[ 10, 20, 30, 40 ];
    echo("v_sum=", v_sum(vec,2,1)); // is 20+30=50
    echo("v_sum=", v_sum(vec));
    echo("v_cumsum=", v_cumsum(vec));
}

// FUNCTION: is_String(x)
//   Returns true if x is a string, false otherwise.
function is_string(x) =
	x == U || len(x) == U
		? false // if U, a boolean or a number
		: len(str(x,x)) == len(x)*2; // if an array, this is false

// FUNCTION: is_array(x)
//   Returns true if x is an array, false otherwise.
function is_array(x) = is_string(x) ? false : len(x) != U;

function identity(d)        = d == 0 ? 1 : [for(y=[1:d]) [for(x=[1:d]) x == y ? 1 : 0] ];
function unit_vector(v)     = let(x=v[0], y=v[1], z=v[2]) [x/norm(v), y/norm(v), z/norm(v)];
function skew_symmetric(v)  = let(x=v[0], y=v[1], z=v[2]) [[0, -z, y], [z, 0, -x], [-y, x, 0]];
function tensor_product1(u) = let(x=u[0], y=u[1], z=u[2]) [[x*x, x*y, x*z], [x*y, y*y, y*z], [x*z, y*z, z*z]];
function v_rotate(a, v)
    = is_array(a)
? let(rx=a[0], ry=a[1], rz=a[2])
    [[1, 0, 0],              [0, cos(rx), -sin(rx)], [0, sin(rx), cos(rx)]]
  * [[cos(ry), 0, sin(ry)],  [0, 1, 0],              [-sin(ry), 0, cos(ry)]]
  * [[cos(rz), -sin(rz), 0], [sin(rz), cos(rz), 0],  [0, 0, 1]]
    : let(uv=unit_vector(v))
    cos(a)*identity(3) + sin(a)*skew_symmetric(uv) + (1 - cos(a))*tensor_product1(uv);

 /*echo(rotate(90, X) * [1, 0, 0]);*/
 /*echo(rotate(90, X) * [0, 1, 0]);*/
 /*echo(rotate(90, X) * [0, 0, 1]);*/

function lerp(v0, v1, t) =  (1-t)*v0 + t*v1;

if($test_mode)
{
    assert(lerp(-1, 1, 0) == -1);
    assert(lerp1(-1, 1, .5) == 0);
    assert(lerp1(-1, 1, 1) == 1);
}

if($test_mode)
{
    assert_v(fallback(U,1), 1);
}

function fallback(a, b) = a==U?b:a;

// echo(fallback(U,[U, 1]));
function v_fallback(a,v,i=0) = (a!=U || i > len(v)-1) ? a : v_fallback(v[i],v,i+1);

function zip(a,b,start=0,end) = [for(i=[start:1:fallback(end,len(a)-1)]) [a[i],b[i]] ];
function zip_v(v,start=0,end) = [for(i=[start:1:fallback(end,len(v[0])-1)]) v_i(v,i) ];

if($test_mode)
{
    vec_a = [0,4];
    vec_b = [1,5];
    vec_c = [2,6];
    vec_d = [3,7];
    assert_v(zip(vec_a,vec_b),[[0,1],[4,5]]);
    assert_v(zip_v([vec_a,vec_b]),[[0,1],[4,5]]);
    assert_v(zip_v([vec_a,vec_b,vec_c,vec_d]), [[0,1,2,3],[4,5,6,7]]);
}

function vv_fallback(v,start=0,end) =
let(z = zip_v(v))
[
for(i=[start:1:fallback(end,len(v[0])-1)])
    v_fallback(v=z[i],i=0)
];

if($test_mode)
{
    vec_a=[ 10,  U,   U, 40 ];
    vec_b=[ 10,  U,  30,  U ];
    vec_c=[  U, 20,   U, 40 ];
    assert(v_fallback(a=5, v=vec_a), 5);
    assert_v(vv_fallback(v=[vec_a, vec_b,vec_c]), [10,20,30,40]);
}

function fn_from_r(r) =
                    $fn > 0.0 ?
                    ($fn >= 3 ? $fn : 3)
                    :
                    ceil(max(min(360.0 / $fa, r*2*PI / $fs), 5));

function fn_from_d(d) =
                    $fn > 0.0 ?
                    ($fn >= 3 ? $fn : 3)
                    :
                    ceil(max(min(360.0 / $fa, d*PI / $fs), 5));

module assert_v(val, expected, message)
{
    if(len(val) > 0)
    {
        if(len(val) != len(expected))
        {
            echo("assertion, not equal length of arrays", val, expected);
            assert(val == expected, message);
        }
        for(i=[0:len(val)])
        {
            if(val[i] != expected[i])
            {
                echo("assertion, unexpected value at index", i, val, expected);
                assert(val == expected, message);
            }
        }

    }
    else
    {
        if(val != expected)
        {
            echo("assertion, unexpected value", val, expected);
            assert(val == expected, message);
        }
    }
}

function spread(v0,v1,a) =
a>=2 ?
    [for(i=[0:1/(a-1):1]) lerp(v0,v1,i)]
:
    [lerp(v0,v1,.5)]
;

if($test_mode)
{
    assert_v(spread(-1, 1, 1), [0]);
    assert_v(spread(-1, 1, 2), [-1,1]);
    assert_v(spread(-1, 1, 3), [-1,0,1]);
    // fails because of float inaccuracy
    /*assert_v(spread(-1, 1, 4), [-1,-1/3,1/3,1]);*/
    assert_v(spread(-1, 1, 5), [-1,-.5,0,.5,1]);
}

// the apothem (inradius) is the distance from the center of a regular
// polygon to the flat side (not a vertex)
function apothem(circumradius, fn) = circumradius*cos(180/fn);
function inradius(circumradius, fn) = circumradius*cos(180/fn);;
// the circumradius (outradius) is the distance from the center of a regular
// polygon to a vertex
function circumradius(apothem, fn) = apothem / cos(180/fn);
function outradius(apothem, fn) = apothem / cos(180/fn);
function fn_radius(r, fn) = apothem(r,fn);
function hex_radius(r) = apothem(r, 6);

if($test_mode)
{
    assert_v(apothem(circumradius(5,6)), circumradius(apothem(5),6));
}

function header_col_index(v, col_keys) =
    singlify(
        [for(col_key=col_keys)
        let(result=search([col_key], v[0], index_col_number=0, num_returns_per_match=0))
        result[0][0]
        ]
    );

function geth(S, col_keys, row_index) =
    singlify(
        [for(col_key=col_keys)
            let(col_index = header_col_index(S, col_key))
            S[row_index+1][col_index]
        ]);

if($test_mode)
{
    A = [
    ["Tx", "Ty"],
    [1, 2],
    [3, 4],
    ];

    assert_v(header_col_index(A, "Tx"), 0);
    assert_v(header_col_index(A, "Ty"), 1);

    assert_v(header_col_index(A, ["Ty"]), 1);
    assert_v(header_col_index(A, ["Tx"]), 0);
    assert_v(header_col_index(A, ["Tx", "Ty"]), [0,1]);

    assert_v(geth(A, "Tx", 0), 1);
    assert_v(geth(A, "Tx", 1), 3);
    assert_v(geth(A, "Ty", 0), 2);
    assert_v(geth(A, "Ty", 1), 4);

    assert_v(geth(A, ["Tx","Ty"], 0), [1,2]);
    assert_v(geth(A, ["Tx","Ty"], 1), [3,4]);

}

function v_contains(V, val, start=0, end=U) =
    !is_array(V) ?
        V == val :
        let(e=end==U?len(V):end)
        V[start]==val ? true :
        start == len(V)-1 ? false :
        v_contains(V,val,start+1,end);

if($test_mode)
{
    assert_v(v_contains(0, 0), true);
    assert_v(v_contains(0, 1), false);
    assert_v(v_contains([0,1], 0), true);
    assert_v(v_contains([0,1], 1), true);
    assert_v(v_contains([0,1], 2), false);
}

// helper functions to work on headered-arrays (where first entry is column headers)
function reverse_header(V) = concat([V[0]], reverse(v_slice(V,start=1)));
function concat_header(A,B) =concat([A[0]], v_slice(A,start=1),v_slice(B,start=1));

function take3(v) = [v[0],v[1],v[2]];

function vec3(V) =
let(l = len(V))
l == 3 ? V :
l < 3 ? vec3(concat(V,0)) :
take3(V);

if($test_mode)
{
    assert_v(take3([0,1,0,1]), [0,1,0]);

    assert_v(vec3([0,1]), [0,1,0]);
    assert_v(vec3([0]), [0,0,0]);
    assert_v(vec3([1]), [1,0,0]);
    assert_v(vec3([0,0,1]), [0,0,1]);
    assert_v(vec3([0,0,1,0]), [0,0,1]);
}


timing_belts: Add

timing_belts: Add

/*Parametric belting section generator
 * types GT2 2mm T2.5 T5 T10 MXL
 *
 * (c) ALJ_rprp
 *
 * Derived from http://www.thingiverse.com/
 * thing:19758 By The DoomMeister
 * thing:16627 by Droftarts
 *
 * licence GPL 2.1 or later
 *
 * deal properly with ends
 * allow circular segments
 * length is given in mm not nb of teeth
 * belt is centered at z=0 and extend along x
 *
 * TODO : add ofset for cosmetic teeth liaisons between segments
 *
 * usage :
 * belt_angle(prf = tT2_5, rad=25, bwdth = 6, angle=90,fn=128)
 * belt_len  (prf = tT2_5, belt_width = 6, len = 10)
 */

// profiles
tGT2_2=0;
tT2_5=1;
tT5=2;
tT10=3;
tMXL=4;

/*test_belt();*/

module test_belt() {
    translate([-00.5,0,5.5])cube([1,40,1]);

    belt_len(profile = tT10, belt_width = 10, len = 100);
    translate([0,0,-20])color("red")belt_len(profile = tT5, belt_width = 10, len = 100);
    translate([0,0,-40])color("green")belt_len(profile = tT2_5, belt_width = 10, len = 80);
    translate([0,0,-60])color("blue")belt_len(profile = tGT2_2, belt_width = 10, len = 100);
    translate([0,0,-80])color("orange")belt_len(profile = tMXL, belt_width = 10, len = 100);

    translate([0,0,-0])  belt_angle(tT10,20,10,180);
    translate([0,0,-20]) belt_angle(tT5,15,10,90);
    translate([0,0,-40]) belt_angle(tT2_5,25,10,120);
    translate([0,0,-60]) belt_angle(tGT2_2,30,10,40);
    translate([0,0,-80]) belt_angle(tMXL,30,10,40);

    translate([0,0,-100])color("aquamarine") {
        belt_len(tT2_5,10, 50);
        translate([50,30,0]) rotate([0,0,180]) belt_len(tT2_5,10,50);
        translate([ 0,30,0]) rotate([0,0,180]) belt_angle(tT2_5,15,10,180);
        translate([50,0,0]) rotate([0,0,0]) belt_angle(tT2_5,15,10,180);
    }
}

/* there is no partial rotate extrude in scad, hence the workaround
 * note that the pie slice will silently drop angles > 360 */
module p_slice(radius, angle,height,back_t=0.6) {
    pt_slc = [[0,radius],
           [0 ,-back_t],
           [radius,-back_t],
               [radius+back_t,radius],
                   [radius+back_t,radius*2],
                       [0,radius*2+back_t],
                           [-radius-back_t,radius*2+back_t],
                               [-radius-back_t,radius],
                                   [-radius-back_t,-back_t],
                                       [(radius+back_t)*sin(angle),(radius+back_t)*(1-cos(angle))-back_t]];

    if (angle<=90) {
        linear_extrude(height = height+0.2, center=true)
            polygon( points = pt_slc,
                    paths=[[0,1,2,9]]);
    }else if (angle<=180){
        linear_extrude(height = height+0.2, center=true)
            polygon( points = pt_slc,
                    paths=[[0,1,2,3,4,9]]);
    }else if (angle<=270){
        linear_extrude(height = height+0.2, center=true)
            polygon( points = pt_slc,
                    paths=[[0,1,2,3,4,5,6,9]]);
    }else if (angle<360) {
        linear_extrude(height = height+0.2, center=true)
            polygon( points = pt_slc,
                    paths=[[0,1,2,3,4,5,6,7,8,9]]);
    }
}

dp=5;

module belt_angle(prf = tT2_5, rad=25, bwdth = 6, angle=90,fn=128) {
    av=360/2/rad/3.14159*tpitch[prf];
    bk=bk_thick[prf];

    nn=ceil(angle/av);
    ang=av*nn;
    intersection(){
        p_slice(rad,angle,bwdth,bk_thick[prf]);
        union () {
            for( i = [0:nn]){
                translate ([0,rad,-bwdth/2])rotate ([0,0,av*i])translate ([0,-rad,0])
                    draw_tooth(prf,0,bwdth);
            }
            translate ([0,rad,-bwdth/2]) rotate_extrude(angle = 90, $fn=fn)
                polygon([[rad,0],[rad+bk,0],[rad+bk,bwdth],[rad,bwdth]]);
        }
    }
}

//Outer Module
module belt_len(profile = tT2_5, belt_width = 6, len = 10){
    if ( profile == tT2_5 ) { _belt_len(prf=profile,len = len,bwdth = belt_width);}
    if ( profile == tT5 )   { _belt_len(prf=profile,len = len,bwdth = belt_width);}
    if ( profile == tT10 )  { _belt_len(prf=profile,len = len,bwdth = belt_width);}
    if ( profile == tMXL )	{ _belt_len(prf=profile,len = len,bwdth = belt_width);}
    if ( profile == tGT2_2 ){ _belt_len(prf=profile,len = len,bwdth = belt_width);}
}

//inner module
module _belt_len(prf = -1, len = 10, bwdth = 5) {

    n=ceil(len/tpitch[prf]);

    translate ([0,0,-bwdth/2]) intersection() {
        union(){
            for( i = [0:n]) {
                draw_tooth(prf,i,bwdth);
            }
            translate([-1,-bk_thick[prf],0])cube([len+1,bk_thick[prf],bwdth]);
        }
        translate([0,-bk_thick[prf],0])cube([len,max_h[prf]+bk_thick[prf],bwdth]);
    }
}

module draw_tooth(prf,i,bwdth) {
    if ( prf == tT2_5 ) { translate([tpitch[prf]*i,0,0])
        linear_extrude(height=bwdth) polygon(pf_T2_5);}
    if ( prf == tT5 ) { translate([tpitch[prf]*i,0,0])
        linear_extrude(height=bwdth) polygon(pf_T5);}
    if ( prf == tT10 ) { translate([tpitch[prf]*i,0,0])
        linear_extrude(height=bwdth) polygon(pf_T10);}
    if ( prf == tMXL ) { translate([tpitch[prf]*i,0,0])
        linear_extrude(height=bwdth) polygon(pf_MXL);}
    if ( prf == tGT2_2 ) { translate([tpitch[prf]*i,0,0])
        linear_extrude(height=bwdth) polygon(pf_GT2_2);}
}

/************************************
 *				DATA TABLES					*
 ************************************/
    tpitch = [2,2.5,5,10,2.032];
    bk_thick=[0.6,0.6,1,2,0.64];
    max_h=[0.76447, 0.699911, 1.189895, 2.499784, 0.508035];

    pf_GT2_2=  [[ 0.747183,-0.5     ],[ 0.747183, 0       ],[ 0.647876, 0.037218],
    [ 0.598311, 0.130528],[ 0.578556, 0.238423],[ 0.547158, 0.343077],
    [ 0.504649, 0.443762],[ 0.451556, 0.53975 ],[ 0.358229, 0.636924],
    [ 0.2484  , 0.707276],[ 0.127259, 0.750044],[ 0       , 0.76447 ],
    [-0.127259, 0.750044],[-0.2484  , 0.707276],[-0.358229, 0.636924],
    [-0.451556, 0.53975 ],[-0.504797, 0.443762],[-0.547291, 0.343077],
    [-0.578605, 0.238423],[-0.598311, 0.130528],[-0.648009, 0.037218],
    [-0.747183, 0       ],[-0.747183,-0.5]];
pf_T2_5=   [[-0.839258,-0.5     ],[-0.839258, 0       ],[-0.770246, 0.021652],
    [-0.726369, 0.079022],[-0.529167, 0.620889],[-0.485025, 0.67826 ],
    [-0.416278, 0.699911],[ 0.416278, 0.699911],[ 0.484849, 0.67826 ],
    [ 0.528814, 0.620889],[ 0.726369, 0.079022],[ 0.770114, 0.021652],
    [ 0.839258, 0       ],[ 0.839258,-0.5]];
pf_T5= 	  [[-1.632126,-0.5     ],[-1.632126, 0       ],[-1.568549, 0.004939],
    [-1.507539, 0.019367],[-1.450023, 0.042686],[-1.396912, 0.074224],
    [-1.349125, 0.113379],[-1.307581, 0.159508],[-1.273186, 0.211991],
    [-1.246868, 0.270192],[-1.009802, 0.920362],[-0.983414, 0.978433],
    [-0.949018, 1.030788],[-0.907524, 1.076798],[-0.859829, 1.115847],
    [-0.80682 , 1.147314],[-0.749402, 1.170562],[-0.688471, 1.184956],
    [-0.624921, 1.189895],[ 0.624971, 1.189895],[ 0.688622, 1.184956],
    [ 0.749607, 1.170562],[ 0.807043, 1.147314],[ 0.860055, 1.115847],
    [ 0.907754, 1.076798],[ 0.949269, 1.030788],[ 0.9837  , 0.978433],
    [ 1.010193, 0.920362],[ 1.246907, 0.270192],[ 1.273295, 0.211991],
    [ 1.307726, 0.159508],[ 1.349276, 0.113379],[ 1.397039, 0.074224],
    [ 1.450111, 0.042686],[ 1.507589, 0.019367],[ 1.568563, 0.004939],
    [ 1.632126, 0       ],[ 1.632126,-0.5]];
pf_T10=    [[-3.06511 ,-1       ],[-3.06511 , 0       ],[-2.971998, 0.007239],
    [-2.882718, 0.028344],[-2.79859 , 0.062396],[-2.720931, 0.108479],
    [-2.651061, 0.165675],[-2.590298, 0.233065],[-2.539962, 0.309732],
    [-2.501371, 0.394759],[-1.879071, 2.105025],[-1.840363, 2.190052],
    [-1.789939, 2.266719],[-1.729114, 2.334109],[-1.659202, 2.391304],
    [-1.581518, 2.437387],[-1.497376, 2.47144 ],[-1.408092, 2.492545],
    [-1.314979, 2.499784],[ 1.314979, 2.499784],[ 1.408091, 2.492545],
    [ 1.497371, 2.47144 ],[ 1.581499, 2.437387],[ 1.659158, 2.391304],
    [ 1.729028, 2.334109],[ 1.789791, 2.266719],[ 1.840127, 2.190052],
    [ 1.878718, 2.105025],[ 2.501018, 0.394759],[ 2.539726, 0.309732],
    [ 2.59015 , 0.233065],[ 2.650975, 0.165675],[ 2.720887, 0.108479],
    [ 2.798571, 0.062396],[ 2.882713, 0.028344],[ 2.971997, 0.007239],
    [ 3.06511 , 0       ],[ 3.06511 ,-1]];
pf_MXL=    [[-0.660421,-0.5     ],[-0.660421, 0       ],[-0.621898, 0.006033],
    [-0.587714, 0.023037],[-0.560056, 0.049424],[-0.541182, 0.083609],
    [-0.417357, 0.424392],[-0.398413, 0.458752],[-0.370649, 0.48514 ],
    [-0.336324, 0.502074],[-0.297744, 0.508035],[ 0.297744, 0.508035],
    [ 0.336268, 0.502074],[ 0.370452, 0.48514 ],[ 0.39811 , 0.458752],
    [ 0.416983, 0.424392],[ 0.540808, 0.083609],[ 0.559752, 0.049424],
    [ 0.587516, 0.023037],[ 0.621841, 0.006033],[ 0.660421, 0       ],
    [ 0.660421,-0.5]];

error: pathspec 'timing-belts.scad' did not match any file(s) known to git


bulachGlas prototype

bulachGlas prototype

$fn=100;
radius=57;
hClosed=35.5;
dLid=5.3;
radius2=50.5;

module ring() {
    rotate_extrude()translate([57/2-5.3/2,0])circle(d=5.3);
}
module assembly() {
    translate([0,0,hClosed-dLid/2])difference() {
        hull()ring();
        translate([0,0,dLid/2])rotate([90,0,0])cylinder(h=radius,r=dLid,center=true);
    }
    difference() {
        cylinder(h=hClosed-dLid/2,r=radius/2);
        translate([0,0,hClosed])rotate([90,0,0])cylinder(h=radius,r=dLid,center=true);
    }
    translate([0,0,-20])cylinder(r=radius2/2,h=20);
}

difference() {
    translate([32.5/2,0,20])cube([32.5,65,60],center=true);
    assembly();
}

error: pathspec 'bulachGlas.scad' did not match any file(s) known to git


y/carriage-bearing-mount: fix use of linear_bearing_mount

include <config.scad>
include <thing_libutils/system.scad>
include <thing_libutils/attach.scad>
include <thing_libutils/bearing-linear-data.scad>
use <thing_libutils/bearing-linear.scad>

yaxis_carriage_bearing_mount_bottom_thick = 3;
yaxis_carriage_bearing_mount_conn_bottom = [N, Z];
yaxis_carriage_bearing_mount_conn_bearing = [[0,0,yaxis_carriage_bearing_mount_bottom_thick+get(LinearBearingOuterDiameter,yaxis_bearing)/2], Z];

module yaxis_carriage_bearing_mount(part)
{
    // x distance of holes
    screw_dx=28;
    // y distance of holes
    screw_dy=21;

    carriage_plate_thread=ThreadM4;
    carriage_plate_thread_d=lookup(ThreadSize, carriage_plate_thread);

    width = screw_dx+carriage_plate_thread_d*2;
    bearing_OD = get(LinearBearingOuterDiameter, yaxis_bearing);
    depth = max(bearing_OD, screw_dx+carriage_plate_thread_d*2);
    height = 5+yaxis_carriage_bearing_mount_bottom_thick;

    if(part==U)
    {
        difference()
        {
            yaxis_carriage_bearing_mount(part="pos");
            yaxis_carriage_bearing_mount(part="neg");
        }
        %yaxis_carriage_bearing_mount(part="vit");
    }
    else if(part=="pos")
    {
        rcubea ([width, depth, height], align=Z);
    }
    else if(part=="neg")
    {
        for(x=[-1,1])
        for(y=[-1,1])
        translate ([x*screw_dx/2, y*screw_dy/2, -1])
        cylindera(d=carriage_plate_thread_d, h=height+2, align=Z);

    }
    else if(part=="vit")
    {
    }

    translate([0,0,bearing_OD/2+yaxis_carriage_bearing_mount_bottom_thick])
    linear_bearing_mount(
        part=part,
        bearing=yaxis_bearing,
        ziptie_type=ziptie_type,
        ziptie_bearing_distance=ziptie_bearing_distance,
        orient=Y,
        ziptie_dist=4,
        mount_dir_align=Z
        );
}

module part_y_carriage_bearing_mount()
{
    c1=[N,Z];
    attach(c1,yaxis_carriage_bearing_mount_conn_bottom)
    {
        yaxis_carriage_bearing_mount();
    }
}

include <config.scad>
include <thing_libutils/system.scad>
include <thing_libutils/attach.scad>
include <thing_libutils/bearing-linear-data.scad>
use <thing_libutils/bearing-linear.scad>

yaxis_carriage_bearing_mount_bottom_thick = 3;
yaxis_carriage_bearing_mount_conn_bottom = [N, Z];
yaxis_carriage_bearing_mount_conn_bearing = [[0,0,yaxis_carriage_bearing_mount_bottom_thick+get(LinearBearingOuterDiameter,yaxis_bearing)/2], Z];

module yaxis_carriage_bearing_mount(part)
{
    // x distance of holes
    screw_dx=28;
    // y distance of holes
    screw_dy=21;

    carriage_plate_thread=ThreadM4;
    carriage_plate_thread_d=lookup(ThreadSize, carriage_plate_thread);

    width = screw_dx+carriage_plate_thread_d*2;
    bearing_OD = get(LinearBearingOuterDiameter, yaxis_bearing);
    depth = max(bearing_OD, screw_dx+carriage_plate_thread_d*2);
    height = 5+yaxis_carriage_bearing_mount_bottom_thick;

    if(part==U)
    {
        difference()
        {
            yaxis_carriage_bearing_mount(part="pos");
            yaxis_carriage_bearing_mount(part="neg");
        }
    }
    else if(part=="pos")
    {
        rcubea ([width, depth, height], align=Z);
    }
    else if(part=="neg")
    {
        for(x=[-1,1])
        for(y=[-1,1])
        translate ([x*screw_dx/2, y*screw_dy/2, -1])
        cylindera(d=carriage_plate_thread_d, h=height+2, align=Z);

        translate([0,0,bearing_OD/2+yaxis_carriage_bearing_mount_bottom_thick])
        linear_bearing_mount(
            bearing=yaxis_bearing,
            ziptie_type=ziptie_type,
            ziptie_bearing_distance=ziptie_bearing_distance,
            orient=Y,
            ziptie_dist=4
            );
    }
    else if(part=="vit")
    {
        translate([0,0,bearing_OD/2+yaxis_carriage_bearing_mount_bottom_thick])
        linear_bearing(yaxis_bearing, orient=Y);
    }
}

module part_y_carriage_bearing_mount()
{
    c1=[N,Z];
    attach(c1,yaxis_carriage_bearing_mount_conn_bottom)
    {
        yaxis_carriage_bearing_mount();
    }
}