Add a sample to illustrate use of new mesh shapes

/**
 * Samples using the camelSCAD library.
 *
 * A simple mesh grid
 *
 * @author jsconan
 * @license CC0-1.0
 */

// As we need to use some shapes, use the right entry point of the library
use <../shapes.scad>
include <../core/constants.scad>

// We will render the object using the specifications of this mode
renderMode = MODE_PROD;

// Defines the dimensions of the object
length = 120;
width = 120;
thickness = 2;
corner = 8;
paddingX = 6;
paddingY = 6;
holeDiameter = 5;
holeIntervalX = length - 2 * holeDiameter;
holeIntervalY = width - 2 * holeDiameter;

cellCountX = 10;
cellCountY = 10;
cellSpaceX = 1;
cellSpaceY = 1;
meshLength = length - 2 * paddingX;
meshWidth  = width - 2 * paddingY;

// Sets the minimum facet angle and size using the defined render mode.
// Displays a build box visualization to preview the printer area.
applyMode(mode=renderMode) {
    difference() {
        cushion([length, width, thickness], d=corner);

        negativeExtrude(thickness, direction=2) {
            translate([holeIntervalX, holeIntervalY, 0] / -2) {
                repeat2D(countX=2, countY=2, intervalX=[holeIntervalX, 0, 0], intervalY=[0, holeIntervalY, 0]) {
                    circle(d=holeDiameter);
                }
            }

            mesh(
                size  = [meshLength, meshWidth],
                count = [cellCountX, cellCountY],
                gap   = [cellSpaceX, cellSpaceY],
                linear = true,
                even = true,
                pointy = false
            );
        }
    }
}

error: pathspec 'samples/mesh-grid.scad' did not match any file(s) known to git


initial version of new fork component, minimzed to a holes distancing part

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


materials: add some materials, and material module

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


printing multiple elements at a time

printing multiple elements at a time

wall = 1.75;
spacing = 1.3;
l = 3.2;
size = [90+2*wall, 41, 15];

module tooth_()
{
  size = 4;
  difference()
  {
    cube([l, size, 16]);
    translate([0, 0, 16+l/2.5])
      rotate([0, 45, 0])
        translate([0, 0, -l])
          cube([l, size, 2*l]);
  }
}

module element()
{
  // body
  difference()
  {
    cube(size);
    translate(wall*[1, 0, 1])
      cube(size - wall*[2, 1, 1]);
  }

  // side teeth
  for(dy=[5, 25])
    translate([wall+spacing, dy, wall])
    {
      tooth_();
      translate([size[0]-2*(wall+spacing), wall, 0])
        rotate([0, 0, 180])
          tooth_();
    }

  // upper teeth
  for(dx=[0:3])
    translate([wall + 15 + dx*18.5, size[1]-wall-spacing-l, 0])
      translate([0, l, 0])
        rotate([0, 0, -90])
          tooth_();
}

distance = 4;
for(n=[0:1])
  for(m=[0:4])
    translate([n*(size[0]+distance), m*(size[1]+distance), 0])
      element();

wall = 1.75;
spacing = 1.3;
l = 3.2;
size = [90+2*wall, 41, 15];

module tooth_()
{
  size = 4;
  difference()
  {
    cube([l, size, 16]);
    translate([0, 0, 16+l/2.5])
      rotate([0, 45, 0])
        translate([0, 0, -l])
          cube([l, size, 2*l]);
  }
}

module element()
{
  // body
  difference()
  {
    cube(size);
    translate(wall*[1, 0, 1])
      cube(size - wall*[2, 1, 1]);
  }

  // side teeth
  for(dy=[5, 25])
    translate([wall+spacing, dy, wall])
    {
      tooth_();
      translate([size[0]-2*(wall+spacing), wall, 0])
        rotate([0, 0, 180])
          tooth_();
    }

  // upper teeth
  for(dx=[0:3])
    translate([wall + 15 + dx*18.5, size[1]-wall-spacing-l, 0])
      translate([0, l, 0])
        rotate([0, 0, -90])
          tooth_();
}

element();


sketch an LCD support 3D model

sketch an LCD support 3D model

$fn = 20;
eps = 1e-3;

// TODO: Proper dimensions.
size_x = 50;
size_y = 20;
size_z = 7;
width = 4;

pin_length = 3;
pin_radius = 1;
pin_offset_left = 2;
pin_offset_right = pin_offset_left;
pin_offset_top = 2;
pin_offset_bottom = 2;

translate([-size_x/2, 0, 0]) {
  cube([size_x, width, size_z]);
  cube([width, size_y, size_z]);
  translate([size_x - width, 0, 0]) {
    cube([width, size_y, size_z]);
  };
  translate([pin_offset_left, pin_offset_bottom, -pin_length]) {
    cylinder(pin_length + eps, pin_radius);
  }
  translate([size_x - pin_offset_right, pin_offset_bottom, -pin_length]) {
    cylinder(pin_length + eps, pin_radius);
  }
  translate([pin_offset_left, size_y - pin_offset_top, -pin_length]) {
    cylinder(pin_length + eps, pin_radius);
  }
  translate([size_x - pin_offset_right, size_y - pin_offset_top, -pin_length]) {
    cylinder(pin_length + eps, pin_radius);
  }
}

error: pathspec '3d/lcd_support_v1.scad' did not match any file(s) known to git


deleted several

deleted several

echo("608zz_run_free - cones for thread return on 608zz bearing");
// my_bearing_cutter() is for cutting into other stuff, not otherwise representing
$fn=128;

module my_bearing_cutter(
shaftlen=20,
wholeH=7.1,
bevel=.55,
outD=22.15,
outwall_thk=2.3,
inspinD=12.6,
inspinID=8,
inspincut=1.5,
){
	// bevel on outside perimeters
	difference(){
		union(){
			translate([0,0,-(wholeH / 2)+bevel/2])
				cylinder(r1=(outD-bevel*2)/2, r2=outD/2, h=.5, center=true);
			translate([0,0,wholeH / 2 - bevel/2])
				cylinder(r1=outD/2, r2=(outD-bevel*2)/2, h=.5, center=true);
		}
		cylinder(r=(outD-bevel*2)/2, h=wholeH+.2, center=true);
	}
	//outside running surface and body
	cylinder(r=outD/2, h=wholeH-1, center=true);
	// post-bevel rim
	difference(){
		cylinder(r=(outD-bevel*2)/2, h=wholeH, center=true);
		cylinder(r=(outD - outwall_thk)/2, h=wholeH+.2, center=true);
	}
	// slightly fatter-than-reality insiderim
	difference(){
		cylinder(r=inspinD/2, h=wholeH+inspincut, center=true);
		cylinder(r=inspinID/2, h=wholeH+inspincut, center=true);
	}
	if (shaftlen > 0){
		#cylinder(r=inspinID/2, h=shaftlen, center=true);
	}
}

module freewheel (outsideD=28, sidewallthk=1.2, shaftage=8, bearingH=7.1){
translate([0,0,+bearingH/2])
	difference(){
		translate([0,0,-bearingH/2+sidewallthk])
			cylinder(r1=outsideD/2, r2=22.15/2, h=sidewallthk+bearingH/2, center=true);
		translate([0,0,0])
			my_bearing_cutter();
	}
	echo("freewheel half");
}

module freewheel_model (shaft=30, spacebear=7.1/2){
	for(i=[90,-90]){
		translate([0,spacebear*i/abs(i),0]) rotate([i,0,0])
			freewheel(shaftlen=shaft/2);
	}
}

// print (in two halves) a snug fitting pully
// so that thread runs on steel

module print_freewheel(){
	translate([0,-(30+1)/2,0])
		freewheel();
	translate([0,(30+1)/2,0])
		freewheel();
}

//freewheel_model();

print_freewheel();

//my_bearing_cutter();

echo("608zz_run_free - cones for thread return on 608zz bearing");
// my_bearing_cutter() is for cutting into other stuff, not otherwise representing
$fn=128;

module my_bearing_cutter(
shaftlen=20,
wholeH=7.1,
bevel=.55,
outD=22.15,
outwall_thk=2.3,
inspinD=12.6,
inspinID=8,
inspincut=1.5,
){
	// bevel on outside perimeters
	difference(){
		union(){
			translate([0,0,-(wholeH / 2)+bevel/2])
				cylinder(r1=(outD-bevel*2)/2, r2=outD/2, h=.5, center=true);
			translate([0,0,wholeH / 2 - bevel/2])
				cylinder(r1=outD/2, r2=(outD-bevel*2)/2, h=.5, center=true);
		}
		cylinder(r=(outD-bevel*2)/2, h=wholeH+.2, center=true);
	}
	//outside running surface and body
	cylinder(r=outD/2, h=wholeH-1, center=true);
	// post-bevel rim
	difference(){
		cylinder(r=(outD-bevel*2)/2, h=wholeH, center=true);
		cylinder(r=(outD - outwall_thk)/2, h=wholeH+.2, center=true);
	}
	// slightly fatter-than-reality insiderim
	difference(){
		cylinder(r=inspinD/2, h=wholeH+inspincut, center=true);
		cylinder(r=inspinID/2, h=wholeH+inspincut, center=true);
	}
	if (shaftlen > 0){
		#cylinder(r=inspinID/2, h=shaftlen, center=true);
	}
}

module freewheel (outsideD=28, sidewallthk=1.2, shaftage=8, bearingH=7.1){
translate([0,0,+bearingH/2])
	difference(){
		translate([0,0,-bearingH/2+sidewallthk])
			cylinder(r1=outsideD/2, r2=22.15/2, h=sidewallthk+bearingH/2, center=true);
		translate([0,0,0])
			my_bearing_cutter();
	}
	echo("freewheel half");
}

module freewheel_model (shaft=30, spacebear=7.1/2){
	for(i=[90,-90]){
		translate([0,spacebear*i/abs(i),0]) rotate([i,0,0])
			freewheel(shaftlen=shaft/2);
	}
}

module print_freewheel(){
	translate([0,-(30+1)/2,0])
		freewheel();
	translate([0,(30+1)/2,0])
		freewheel();
}

//freewheel_model();
print_freewheel();
//my_bearing_cutter();


Got the basic shelf working

Got the basic shelf working

Need to make it be able to handle a top and a bottom shelf, as well as
making the whole thing recursive

// www.github.com/agupta231

// user set variables
initial_side_length = 100;
initial_side_height = 30;
padding_ratio = .05;

knob_ratio = .2;

max_iterations = 3;

top_opening_ratio = .3;
bottom_opening_ratio = .7;

echo(version());

module shelf(length, depth, height) {
    difference() {
        cube([length, depth, height], center = true);

        translate([0, 0, length * padding_ratio]) {
            cube([(1 - padding_ratio) * length, depth - length * padding_ratio, height], center = true);
        }
    }

    translate([0, (1 + knob_ratio / 2) * depth / 2 ,0])
    cube([length * knob_ratio, depth * knob_ratio / 2, height * knob_ratio], center = true);
}

module pattern(current_iteration, starting_pos, length, depth, height) {
    padding = length * padding_ratio;

    length_new = length / 2 - padding;
    height_new = (height - padding * 3) / 2;

    if(current_iteration % 2 == 0) {
        echo(starting_pos + [0, depth / 2, 0]);

        translate(starting_pos + [0, (length_new * top_opening_ratio) / 2, 0]) {
            shelf(length_new, length_new * top_opening_ratio, height_new);
        }
    }
    else if(current_iteration % 2 == 1) {

    }
}

#shelf(initial_side_length, initial_side_length * bottom_opening_ratio, initial_side_height);

pattern(0, [0, 35, 0], initial_side_length, initial_side_length, initial_side_height);


Cleaned up

Cleaned up

/*
The MIT License (MIT)

Copyright (c) 2015 Paolo Negrini

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

//$fn = 250;
//Need to fix servo tilt suport issue. The spheric part does not move with the arm when you change xPos parameter
// RPi supports does not touch the bottom of the case
include <rpi.scad>;
PIcameraDiam = 8;
PIcameraX = 25;
PIcameraY = 25;

mik = 2;
shellThickness = 3;
supportBaseHeight = 5;
//5.4 is the height of the
baseHeight = 31 + shellThickness - 5.4;
tolerance = 1.5;
gimballWidth = 45; //for 50 gives R = 86

R = sqrt(3 * gimballWidth * gimballWidth) / 2;
panSupport = sqrt(R * R - (gimballWidth * gimballWidth / 4));
gimballPivotR = R / 2;
supportY = 2 * sqrt(R * R - (gimballWidth / 2) * (gimballWidth / 2));
supportX = R - gimballWidth / 2;
supportZ = 1.1 * R;

servoX = 11.8;
servoY = 22.2;

servoHornThickness = 5.5;
servoHornWidth = 8;
servoHornLenght = 32;

servoClerance = 31 - 16 - servoHornThickness;
eccentricity = 22.2 / 2 - 5;
servoBodySupport = 20;

screwDiam = 3;
screwLenght = 10;
screwTolerance = 0.3;

Piwidth = 56;
Pilength = 85;
Piheight = 1.5;

boxLength = Pilength + 8;
boxDepth = 2 * R + 10;
boxHeight = 48;
boxThickness = 1;
topCoverHeight = 15;

servoPanZ = boxHeight - 20 + topCoverHeight - servoClerance;
servoPanBoxX = (servoX - 2 * boxThickness - tolerance);
servoPanBoxThickness = 2;

function RatX(x) = sqrt(R * R - (x * x));

//---------------------------------------
module panSupport() {
    //rotate([0,270,0])servoTiltSupport(15,"pan");
    difference() {
        union() {
            color("blue", 0.5) multmatrix(m = [
                [1, 0, 0, 0],
                [0, 1, 0.4, 0],
                [0, 0, 1, 0],
                [0, 0, 0, 1]
            ]) cylinder(h = servoPanZ, d1 = boxDepth, d2 = servoY + 2 * servoPanBoxThickness, center = true);
            //Creates bottom support blocks add -mik to y translate if you want to zero the mechanical interference
            translate([0, boxDepth / 2 - 20 / 2 - mik, -servoPanZ / 2 + 5]) cube([boxHeight / 2 + servoPanBoxX, 20, 10], center = true);
            mirror([0, 1, 0]) translate([0, boxDepth / 2 - 20 / 2 - mik, -servoPanZ / 2 + 5]) cube([boxHeight / 2 + (servoX - 2 * boxThickness - tolerance), 20, 10], center = true);
        }

        //Cuts the support from a cylinder
        translate([boxHeight / 2 + (servoX - 2 * boxThickness - tolerance), 0, 0]) cube([boxHeight, boxDepth + 10, boxHeight - 20 + topCoverHeight - servoClerance], center = true);
        mirror(1, 0, 0) translate([boxHeight / 2 + (servoX - 2 * boxThickness - tolerance), 0, 0]) cube([boxHeight, boxDepth + 10, boxHeight - 20 + topCoverHeight - servoClerance], center = true);

        color("blue", 0.5) multmatrix(m = [
            [1, 0, 0, 0],
            [0, 1, 0.4, 0],
            [0, 0, 1, 0],
            [0, 0, 0, 1]
        ]) cylinder(h = servoPanZ, d1 = boxDepth - 10, d2 = servoY - 10, center = true);

        //Cuts the support to fit case
        translate([0, +eccentricity, 10]) cube([servoPanBoxX + servoPanBoxThickness + 4, servoY + servoPanBoxThickness + 1.5, 20], center = true);
        translate([0, -(boxDepth / 2 + 10 - mik), -servoPanZ / 2 + 5]) cube([boxHeight / 2 + servoPanBoxX, 20, 10], center = true);

        //Slot for video
        translate([0, boxDepth / 2 - 10, -servoPanZ / 2 + 5]) rotate([90, 0, 0]) scale([1.2, 1.5, 1]) cube([8, 20, 20], center = true);

    }
    rotate([0, 90, 90]) translate([3.25, 0, 0]) miscroServoSupport();

}

//---------------------------------------
//This was the verion for RPi v1
module panSupportRPiV1() {
    //rotate([0,270,0])servoTiltSupport(15,"pan");
    difference() {
        union() {
            color("blue", 0.5) multmatrix(m = [
                [1, 0, 0, 0],
                [0, 1, 0.4, 0],
                [0, 0, 1, 0],
                [0, 0, 0, 1]
            ]) cylinder(h = servoPanZ, d1 = boxDepth, d2 = servoY + 2 * servoPanBoxThickness, center = true);
            //Creates bottom support blocks add -mik to y translate if you want to zero the mechanical interference
            translate([0, boxDepth / 2 - 20 / 2 - mik, -servoPanZ / 2 + 5]) cube([boxHeight / 2 + servoPanBoxX, 20, 10], center = true);
            mirror([0, 1, 0]) translate([0, boxDepth / 2 - 20 / 2 - mik, -servoPanZ / 2 + 5]) cube([boxHeight / 2 + (servoX - 2 * boxThickness - tolerance), 20, 10], center = true);
        }

        //Cuts the support from a cylinder
        translate([boxHeight / 2 + (servoX - 2 * boxThickness - tolerance), 0, 0]) cube([boxHeight, boxDepth + 10, boxHeight - 20 + topCoverHeight - servoClerance], center = true);
        mirror(1, 0, 0) translate([boxHeight / 2 + (servoX - 2 * boxThickness - tolerance), 0, 0]) cube([boxHeight, boxDepth + 10, boxHeight - 20 + topCoverHeight - servoClerance], center = true);

        color("blue", 0.5) multmatrix(m = [
            [1, 0, 0, 0],
            [0, 1, 0.4, 0],
            [0, 0, 1, 0],
            [0, 0, 0, 1]
        ]) cylinder(h = servoPanZ, d1 = boxDepth - 10, d2 = servoY - 10, center = true);

        //Cuts the support to fit case
        translate([0, +eccentricity, 10]) cube([servoPanBoxX + servoPanBoxThickness + 4, servoY + servoPanBoxThickness + 1.5, 20], center = true);
        translate([0, -(boxDepth / 2 + 10 - mik), -servoPanZ / 2 + 5]) cube([boxHeight / 2 + servoPanBoxX, 20, 10], center = true);

        //Slot for video
        translate([0, boxDepth / 2 - 10, -servoPanZ / 2 + 5]) rotate([90, 0, 0]) scale([1.2, 1.5, 1]) cube([8, 20, 20], center = true);

    }
    rotate([0, 90, 90]) translate([3.25, 0, 0]) miscroServoSupport();

}

module miscroServoSupport() {

    translate([-servoBodySupport / 2, 0, eccentricity]) {
        //This is the servo box
        difference() {
            cube([servoBodySupport, 12 + 1 + shellThickness, 22.2 + 1 + shellThickness], center = true);
            cube([servoBodySupport, 12 + 1, 22.2 + 1], center = true);

            //Servo cable slot
            translate([0, 0, -2 * eccentricity]) cube([100, 3, 3], center = true);

        }

    }

}

//--------------------------------
module box(Xdim, Ydim, Zdim, thickness, application)
    //Creates a box, dimensions are internal
    {
        difference() {

            cube([Xdim + thickness, Ydim + thickness, Zdim], center = true);
            translate([0, 0, thickness / 2]) cube([Xdim, Ydim, Zdim], center = true);
            if (application == "servo") {
                translate([-Xdim / 2, 0, -0.5 * Zdim]) cube([5, Ydim + 2 * thickness, Zdim / 2 + thickness], center = true);
                translate([+Xdim / 2, 0, -0.5 * Zdim]) cube([5, Ydim + 2 * thickness, Zdim / 2 + thickness], center = true);
                translate([+Xdim / 2, 0, 0]) cube([thickness / 2, 0.3 * Ydim, Zdim], center = true);
                translate([-Xdim / 2, 0, 0]) cube([thickness / 2, 0.3 * Ydim, Zdim], center = true);
            }
        }
    }

//Baseplate for pan mechanism
module base(servo) {
        difference() {

            {
                minkowski() {
                    cylinder(r = R + mik, h = supportBaseHeight);
                    rotate([90, 0, 0]) cylinder(r = mik, h = 1);
                }

                //This to create a anchoring mechanism with the pan base
                //translate([0, 0,-mik])cylinder(r = R + mik+3, h = 2);
            }
            if (servo == true) {
                translate([0, 0, -supportZ - servoHornThickness - mik]) rotate([0, 90, 0]) servoHorn("cross");
                cylinder(r = 2.5, h = 15, center = true);
            }
        }
    }

module supportSection() {
        intersection() {
            difference() {
                sphere(R);
                cube([gimballWidth, 2 * gimballWidth, 2 * gimballWidth], center = true);

            }
            translate([R - supportX / 2, 0, 0]) cube([supportX, supportY, 10], center = true);
        }
    }
    //-------------------------

    //This creates the supporting pillar for the camera shell
    module tiltSupport()

    {
        union() {
            difference() {
                sphere(R);
                cube([gimballWidth, 2 * gimballWidth, 2 * gimballWidth], center = true);
                translate([-gimballWidth, 0, 0]) cube([2 * gimballWidth, 2 * gimballWidth, 2 * gimballWidth], center = true);

            }

            hull() {
                translate([0, 0, -5]) supportSection();
                translate([0, 0, -supportZ]) supportSection();
            }
        }

    }

module servoTiltSupport(xPos, Pos) {
    //The module ned to be rewritten to be easy to read!!!
        //Need to center the servo shaft, the second figure is the distance form border
        supportPosition = xPos;
        //Need to adjust the clearance to account for the Xpos
        supportCurvature = 30;

        rotate([-0, 0, 0]) difference() {

            union() {

                difference() {
                    translate([-shellThickness / 2 + supportPosition, 0, 0]) {
                        cube([shellThickness, 30, 1.8 * RatX(gimballWidth / 2)], center = true);
                    }

               difference(){sphere(5*R);sphere(R - shellThickness);}
                       difference() {
                        }
                    }

                translate([-servoBodySupport / 2 + supportPosition, 0, eccentricity]) {
                    //This is the servo box
                     difference() {
                        cube([servoBodySupport, 12 + tolerance + shellThickness + 3 , 22.2 + 3 + shellThickness], center = true);
                        cube([servoBodySupport, 12 + tolerance, 22.2 + 1.1*tolerance], center = true);

                        //Servo cable slot
                        translate([0, 0, -2 * eccentricity]) cube([100, 4, 4], center = true);

                    }

                }
            }

            //This is the slot in the servo arm
            translate([servoClerance + 8 + shellThickness, 0, eccentricity]) {
                cube([20 + tolerance, 12 + tolerance, 32.2 ], center = true);
                translate([-31 / 2, 0, 0]) cube([31 + 1, 12, 22.2 + + 1.1*tolerance], center = true);

            }
        }

        //This is the curved extra support for the connection with the gimball internal shell
             translate([0, 0, 0])SUB_tiltwedge(xPos);
             mirror([0,0,1])translate([0, 0, 0])SUB_tiltwedge(xPos);

    }

    //-------------------------

module SUB_tiltwedge(xPos) {
   supportCurvature = 30;

            difference() {
                translate([12, 0, +RatX(xPos) - 10])
                difference() {
                    cube([16, 30, 50], center = true);
                    translate([-supportCurvature, 0, -supportCurvature]) sphere(r = supportCurvature + 20, center=true);

                }

                difference() {
                    sphere(10*R);

                    sphere(R - shellThickness);

                }

            }

}

module cameraSupport() {
        difference() {
            difference() {
                sphere(R);
                sphere(R - shellThickness);
            }

            translate([R + gimballWidth / 2, 0, 0]) cube([2 * R, 2 * R, 2 * R], center = true);
            translate([-R - gimballWidth / 2, 0, 0]) cube([2 * R, 2 * R, 2 * R], center = true);
              //Creates camera support
            translate([0, R - 7, 0]) cube([PIcameraX + tolerance, 3, PIcameraY + tolerance], center = true);
            translate([0, R - 7, 0]) cube([2, 3, PIcameraY], center = true);
            //Slot for camera wires
            translate([0, R - 8, -PIcameraY / 2 - 2]) cube([PIcameraX - 5, 3, 3], center = true);

            //Hole for the camera
            translate([0, R, 0]) rotate([90, 0, 0]) cube([PIcameraDiam + 2*tolerance, 10, PIcameraDiam + 2*tolerance], center = true);
		translate([0,0.9*R,0])SUB_PiCamHoles(0.3);
            }

        //Need to hardwire the servo dimensions

        {
            servoTiltSupport(gimballWidth/2, "tilt");

        }
        //Pivot mechanism. Need to understand why 0.98 otherwise a layer gets created
        translate([-gimballWidth / 2, 0, 0]) {
            difference() {
                rotate([0, 90, 0]) cylinder(r = panSupport, h = 0.98*shellThickness);
                gimballPivot(1);
                rotate([0, 90, 0]) cylinder(r = gimballPivotR - shellThickness, h = shellThickness);

            }
            gimballPivot(1);
        }
    }

    //-------------------------

module SUB_PiCamHoles(T) {
// T is the tolerance for holes
        translate([PIcameraX/2-2, 0, PIcameraY/2-1])rotate([90,0,0])cylinder(r=1+T,h=10, center=true);
		translate([-(PIcameraX/2-2), 0, PIcameraY/2-1])rotate([90,0,0])cylinder(r=1+T,h=10, center=true);
		translate([PIcameraX/2-2, 0, (PIcameraY/2-1)-12.5])rotate([90,0,0])cylinder(r=1+T,h=10, center=true);
		translate([-(PIcameraX/2-2), 0, (PIcameraY/2-1)-12.5])rotate([90,0,0])cylinder(r=1+T,h=10, center=true);

}

module camBolt() {
    difference(){
         SUB_camBoltFrame();
        SUB_PiCamHoles(0.1);

}
}

module SUB_camBoltFrame(){

translate([PIcameraX/2-2,0,PIcameraY/2-2])rotate([90,0,0])cylinder(r=3,h=8, center=true);
translate([-(PIcameraX/2-2),0,PIcameraY/2-2])rotate([90,0,0])cylinder(r=3,h=8, center=true);
translate([-(PIcameraX/2-2),0,+(PIcameraY/2-2)-12.5])rotate([90,0,0])cylinder(r=3,h=8, center=true);
translate([(PIcameraX/2-2),0,+(PIcameraY/2-2)-12.5])rotate([90,0,0])cylinder(r=3,h=8, center=true);
translate([0,+2.5-4,0]){
    translate([0,0,(PIcameraY/2-2)-12.5])cube([(PIcameraX-2),5,5], center=true);
translate([0,0,(PIcameraY/2-2)])cube([(PIcameraX-2),5,5], center=true);
translate([PIcameraX/2-2.5,0,12.5/2])cube([5,5,(12.5)], center=true);
translate([-(PIcameraX/2-2.5),0,12.5/2])cube([5,5,(12.5)], center=true);
}

}

module servoHorn(type) {
        cube([servoHornThickness, servoHornWidth, servoHornLenght], center = true);
        if (type == "cross") rotate([90, 0, 0]) cube([servoHornThickness, servoHornWidth, servoHornLenght], center = true);
    }
    //-------------------------

module gimballPivot(tolerance) {
        rotate([0, 90, 0])
        difference() {
            cylinder(r = gimballPivotR - tolerance / 2, h = gimballPivotR / 2, center = true);
            cylinder(r = gimballPivotR - 3 + tolerance / 2, h = gimballPivotR / 2, center = true);
        }
    }
    //-------------------------

module support() {
    scaleFactor = (R + tolerance) / R;

    difference() {
        tiltSupport();

        translate([gimballWidth / 2 + servoHornThickness / 2, 0, 0]) rotate([45, 0, 0]) servoHorn("line");
        translate([gimballWidth / 2, 0, 0]) rotate([0, 90, 0]) cylinder(r = 3, h = 30);

    }

    //Need to cut holes in the base for servo and camera cables and the screws
    translate([0, 0, -supportBaseHeight / 2])
    difference() {

        {
            color("blue", 0.5) translate([0, 0, -supportZ - supportBaseHeight]) base(true);
            translate([0, 0, -supportZ - servoHornThickness]) rotate([0, 90, 0]) servoHorn("cross");
            SUB_cameracableDuct();
            translate([0, 0, +supportBaseHeight / 2]) mirror([1, 0, 0]) tiltSupport();
            SUB_mountedPillarScrewHoles();
            translate([-gimballWidth / 2 - supportX / 2, 0, 0]) rotate([0, 0, 180])
            SUB_servocableDuct();

        }

    }

}

module mountedPillar() {
    //Pillar for camera. This one needs to be mounted separately
    difference() {
        mirror([1, 0, 0]) tiltSupport();
        translate([-gimballWidth / 2, 0, 0]) gimballPivot(0);
        translate([-gimballWidth / 2, 0, 0]) gimballPivot(3); {
            SUB_cameracableDuct();
            SUB_mountedPillarScrewHoles();
            translate([-gimballWidth / 2 - supportX / 2, 0, -supportX / 2]) rotate([0, 0, 180])
            SUB_servocableDuct();
        }

    }

}

module SUB_screw(tolerance) {
    cylinder(r = screwDiam / 2 + tolerance, h = screwLenght);
    translate([0, 0, -3]) cylinder(r = 2 * screwDiam / 2 + screwTolerance, h = 4);
}

module SUB_mountedPillarScrewHoles() {
    color("blue", 0.5) translate([-R + supportX / 2 + 2, 0, -supportZ - screwLenght / 2]) {
        translate([0, 0.5 * panSupport, 0]) SUB_screw(-screwTolerance);
        mirror([0, 1, 0]) translate([0, 0.5 * panSupport, 0]) SUB_screw(-screwTolerance);
    }
}

module SUB_servocableDuct() {
    //Duct for servo cable
    {
        translate([0, 0, -supportZ + supportX]) cylinder(r = supportX / 3, h = supportZ + supportX / 2, center = true);
        translate([-supportX, 0, 0]) rotate([0, 120, 0]) cylinder(r = supportX / 3, h = supportX, center = false);
        translate([0, 0, -supportZ - supportX / 3]) rotate([0, 90, 180]) cylinder(r = supportX / 3, h = 0.6 * R, center = false);
    }

}

module SUB_cameracableDuct() {
        //Duct for camera connetion
        translate([-gimballWidth / 2 - 0.5 * supportX, 0, 0]) rotate([0, 0, 90]) {
            translate([0, 0, 0]) rotate([90, 0, 0]) cylinder(r = 26 / 2, h = 0.6 * supportX);
            translate([0, 0, -supportZ / 2]) cube([20, 3, supportZ + 1.1 * supportBaseHeight], center = true);
            translate([0, -R * 0.5 + 13, -supportZ - supportBaseHeight]) rotate([90, 0, 0]) cube([20, 5, R * 0.5], center = true);

        }
    }
    //---------------------------

module connectionSocket() {

    cylinder(r = 3, h = 5);
    translate([-9, -3 / 2, 0]) cube([10, 3, 5]);

}

module PiSupport() {
    difference() {
        translate([0,0,1])cube([4 + 3 / 2 - 0.4, 4 + 3 / 2 - 0.2, 8], center = true);
        cylinder(r = 3 / 2 - 0.2, h = 2 * Piheight + 8, $fs = 0.1);
    }

}

module case () {
    translate([0, 0, -boxHeight / 2 - supportZ - 2 * supportBaseHeight]) {
        difference() {
            minkowski() {
                box(boxLength, boxDepth, boxHeight, boxThickness, "PI");
                //sphere(r = mik);
                cylinder(r = mik, h = 2);
            }
            translate([R - 10, -Piwidth / 2, -boxHeight / 2 - 5 / 2]) connectionSocket();
            translate([-R + 10, -Piwidth / 2, -boxHeight / 2 - 5 / 2]) connectionSocket();
            translate([R - 10, Piwidth / 2, -boxHeight / 2 - 5 / 2]) connectionSocket();
            translate([-R + 10, Piwidth / 2, -boxHeight / 2 - 5 / 2]) connectionSocket();

            translate([0, 0, -boxHeight / 2 - 5 / 2]) cylinder(r = 3, h = 5);

translate([-Pilength / 2, -16, -boxHeight / 2 + 5 + shellThickness]) {
                rpi();
            }
//This is the power inlet. The +6 in z is half the z-lenght of the component
translate([-boxLength/2,-boxDepth/2+8,-boxHeight/2+shellThickness+2*mik+tolerance])cube([15+tolerance,9+tolerance,12], center=true);

        }
        translate([-Pilength / 2, -16, -boxHeight / 2 + 1 + shellThickness]) {
translate ([Pilength-3.5, Piwidth-3.5,-0.1]) PiSupport();
translate ([Pilength-3.5, -0+3.5,-0.1]) PiSupport();
translate ([Pilength-58-3.5, Piwidth-3.5,-0.1]) PiSupport();
translate ([Pilength-58, 0+3.5,-0.1]) PiSupport();
          //translate([25.5, 18, 0]) PiSupport();
            //translate([Pilength - 5, Piwidth - 12.5, 0]) PiSupport();

        }

    }
translate([-boxLength/2+15/2+mik,-boxDepth/2+8,-supportZ-boxHeight-4])rotate([0,0,180])SUB_Power();

}

module topLid() {
    tolerance = 0.02;

    difference() {
        difference() {
            {
                minkowski() {
                    translate([0, 0, -supportZ - supportBaseHeight - topCoverHeight / 2]) cube([boxLength + mik - 1, boxDepth + mik - 1, topCoverHeight], center = true);
                    sphere(r = mik); //cylinder(r = mik, h = 2);
                }
                translate([0, 0, -supportZ - supportBaseHeight]) {
                    scale([1 + tolerance, 1 + tolerance, 1]) base("false");
                    scale([0.9, 0.9, 30]) base("false");

                    //This is the grid an hole for mic.need to re-work the placement definition as it will not work for other box dimensions!!!
                    translate([boxLength / 2 - 5 - mik - boxThickness, -(boxDepth / 2 - 5 - mik - boxThickness), +14 - supportBaseHeight - topCoverHeight / 2]) rotate([0, 180, 0]) SUB_Mic();

                }

            }

        }

        scale([0.98,0.98,1])case ();

    }

//Need to explain the -1.4*supportBaseHeight
difference(){
translate([0,0,-supportZ-1.4*supportBaseHeight])rotate([0,-90,90])testSupport();
       case ();

}

}

module SUB_Mic() {
    translate([-7, 0, 0]) for (i = [1: 6]) {
        translate([i * 2, 0, 0]) cube([1, 10, 2], center = true);
    }
    cylinder(r = 5, h = 2 * topCoverHeight);

}

module SUB_Power(){
	difference(){
		cube([15,9+3,12], center=true);
		translate([2,0,2])cube([15+tolerance,9+tolerance,12], center=true);
	}
}
module assembly(view)
{

space = (view == "explode") ? 20 : 0;

translate([-space,0,0])cameraSupport();
translate([0,0,-space])support();
translate([-3*space,0,0])mountedPillar();
translate([0,0,-3*space])topLid();

//translate([0,0,-4*space-1.5*supportZ])panSupport();
translate([0,0,-6*space])case ();

}

//-------------------------------
module testSupport(xPos, Pos) {
        //Need to center the servo shaft, the seconf figure is the distance form border
        eccentricity = 22.2 / 2 - 5;
        servoBodySupport = 25;
        //Need to adjust the clearance to account for the Xpos
		armLenght = 1.4*(boxDepth/2);
       difference() {

            union() {

                difference() {
                    translate([-shellThickness / 2, 0, 15]) {
                        cube([shellThickness, servoBodySupport, armLenght], center = true);
                    }

                }

                translate([-servoBodySupport / 2, 0, eccentricity]) {
                    //This is the servo box
                    difference() {
                        cube([servoBodySupport, 12 + 1 + shellThickness, 22.2 + 1 + shellThickness], center = true);
                        cube([servoBodySupport, 12 + 1, 22.2 + 1], center = true);

                        //Servo cable slot
                        translate([0, 0, -2 * eccentricity]) cube([100, 4, 4], center = true);

                    }

                }
            }

            //This is the slot in the servo arm. Need to check why -15 in the translate is needed
translate([-(11)+(32.2/2+12/2+tolerance/2)-15, 0, eccentricity]) {

                cube([20 + tolerance, 12+tolerance/2, 32.2 + tolerance], center = true);
                translate([-31/2, 0, 0]) cube([31 + tolerance, 12+tolerance/2, 22.2 + tolerance], center = true);

            }

}

//Dimensions are hardwired, should be parameters!!!
		translate([-10,0,+armLenght/2+15])rotate([270,0,0])linear_extrude(height = servoBodySupport, center = true, convexity = 10, twist = 0)
			//polygon([[0,0],[8,20],[10,0]], convexity = N);
 polygon([[0,0],[10,armLenght/3],[10,0]], convexity = N);

}

//-------------------------

assembly("explode");
//case();
//topLid();
//SUB_Power();

//mountedPillar();

//servoTiltSupport(gimballWidth/2, "tilt");

//cameraSupport();
//support();
//camBolt();

/*
The MIT License (MIT)

Copyright (c) 2015 Paolo Negrini

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

//$fn = 250;
//Need to fix servo tilt suport issue. The spheric part does not move with the arm when you change xPos parameter
// RPi supports does not touch the bottom of the case
include <rpi.scad>;
PIcameraDiam = 8;
PIcameraX = 25;
PIcameraY = 25;

mik = 2;
shellThickness = 3;
supportBaseHeight = 5;
//5.4 is the height of the
baseHeight = 31 + shellThickness - 5.4;
tolerance = 1.5;
gimballWidth = 45; //for 50 gives R = 86

R = sqrt(3 * gimballWidth * gimballWidth) / 2;
panSupport = sqrt(R * R - (gimballWidth * gimballWidth / 4));
gimballPivotR = R / 2;
supportY = 2 * sqrt(R * R - (gimballWidth / 2) * (gimballWidth / 2));
supportX = R - gimballWidth / 2;
supportZ = 1.1 * R;

servoX = 11.8;
servoY = 22.2;

servoHornThickness = 5.5;
servoHornWidth = 8;
servoHornLenght = 32;

servoClerance = 31 - 16 - servoHornThickness;
eccentricity = 22.2 / 2 - 5;
servoBodySupport = 20;

screwDiam = 3;
screwLenght = 10;
screwTolerance = 0.3;

Piwidth = 56;
Pilength = 85;
Piheight = 1.5;

boxLength = Pilength + 8;
boxDepth = 2 * R + 10;
boxHeight = 48;
boxThickness = 1;
topCoverHeight = 15;

servoPanZ = boxHeight - 20 + topCoverHeight - servoClerance;
servoPanBoxX = (servoX - 2 * boxThickness - tolerance);
servoPanBoxThickness = 2;

function RatX(x) = sqrt(R * R - (x * x));

//---------------------------------------
module panSupport() {
    //rotate([0,270,0])servoTiltSupport(15,"pan");
    difference() {
        union() {
            color("blue", 0.5) multmatrix(m = [
                [1, 0, 0, 0],
                [0, 1, 0.4, 0],
                [0, 0, 1, 0],
                [0, 0, 0, 1]
            ]) cylinder(h = servoPanZ, d1 = boxDepth, d2 = servoY + 2 * servoPanBoxThickness, center = true);
            //Creates bottom support blocks add -mik to y translate if you want to zero the mechanical interference
            translate([0, boxDepth / 2 - 20 / 2 - mik, -servoPanZ / 2 + 5]) cube([boxHeight / 2 + servoPanBoxX, 20, 10], center = true);
            mirror([0, 1, 0]) translate([0, boxDepth / 2 - 20 / 2 - mik, -servoPanZ / 2 + 5]) cube([boxHeight / 2 + (servoX - 2 * boxThickness - tolerance), 20, 10], center = true);
        }

        //Cuts the support from a cylinder
        translate([boxHeight / 2 + (servoX - 2 * boxThickness - tolerance), 0, 0]) cube([boxHeight, boxDepth + 10, boxHeight - 20 + topCoverHeight - servoClerance], center = true);
        mirror(1, 0, 0) translate([boxHeight / 2 + (servoX - 2 * boxThickness - tolerance), 0, 0]) cube([boxHeight, boxDepth + 10, boxHeight - 20 + topCoverHeight - servoClerance], center = true);

        color("blue", 0.5) multmatrix(m = [
            [1, 0, 0, 0],
            [0, 1, 0.4, 0],
            [0, 0, 1, 0],
            [0, 0, 0, 1]
        ]) cylinder(h = servoPanZ, d1 = boxDepth - 10, d2 = servoY - 10, center = true);

        //Cuts the support to fit case
        translate([0, +eccentricity, 10]) cube([servoPanBoxX + servoPanBoxThickness + 4, servoY + servoPanBoxThickness + 1.5, 20], center = true);
        translate([0, -(boxDepth / 2 + 10 - mik), -servoPanZ / 2 + 5]) cube([boxHeight / 2 + servoPanBoxX, 20, 10], center = true);

        //Slot for video
        translate([0, boxDepth / 2 - 10, -servoPanZ / 2 + 5]) rotate([90, 0, 0]) scale([1.2, 1.5, 1]) cube([8, 20, 20], center = true);

    }
    rotate([0, 90, 90]) translate([3.25, 0, 0]) miscroServoSupport();

}

//---------------------------------------
//This was the verion for RPi v1
module panSupportRPiV1() {
    //rotate([0,270,0])servoTiltSupport(15,"pan");
    difference() {
        union() {
            color("blue", 0.5) multmatrix(m = [
                [1, 0, 0, 0],
                [0, 1, 0.4, 0],
                [0, 0, 1, 0],
                [0, 0, 0, 1]
            ]) cylinder(h = servoPanZ, d1 = boxDepth, d2 = servoY + 2 * servoPanBoxThickness, center = true);
            //Creates bottom support blocks add -mik to y translate if you want to zero the mechanical interference
            translate([0, boxDepth / 2 - 20 / 2 - mik, -servoPanZ / 2 + 5]) cube([boxHeight / 2 + servoPanBoxX, 20, 10], center = true);
            mirror([0, 1, 0]) translate([0, boxDepth / 2 - 20 / 2 - mik, -servoPanZ / 2 + 5]) cube([boxHeight / 2 + (servoX - 2 * boxThickness - tolerance), 20, 10], center = true);
        }

        //Cuts the support from a cylinder
        translate([boxHeight / 2 + (servoX - 2 * boxThickness - tolerance), 0, 0]) cube([boxHeight, boxDepth + 10, boxHeight - 20 + topCoverHeight - servoClerance], center = true);
        mirror(1, 0, 0) translate([boxHeight / 2 + (servoX - 2 * boxThickness - tolerance), 0, 0]) cube([boxHeight, boxDepth + 10, boxHeight - 20 + topCoverHeight - servoClerance], center = true);

        color("blue", 0.5) multmatrix(m = [
            [1, 0, 0, 0],
            [0, 1, 0.4, 0],
            [0, 0, 1, 0],
            [0, 0, 0, 1]
        ]) cylinder(h = servoPanZ, d1 = boxDepth - 10, d2 = servoY - 10, center = true);

        //Cuts the support to fit case
        translate([0, +eccentricity, 10]) cube([servoPanBoxX + servoPanBoxThickness + 4, servoY + servoPanBoxThickness + 1.5, 20], center = true);
        translate([0, -(boxDepth / 2 + 10 - mik), -servoPanZ / 2 + 5]) cube([boxHeight / 2 + servoPanBoxX, 20, 10], center = true);

        //Slot for video
        translate([0, boxDepth / 2 - 10, -servoPanZ / 2 + 5]) rotate([90, 0, 0]) scale([1.2, 1.5, 1]) cube([8, 20, 20], center = true);

    }
    rotate([0, 90, 90]) translate([3.25, 0, 0]) miscroServoSupport();

}

module miscroServoSupport() {

    translate([-servoBodySupport / 2, 0, eccentricity]) {
        //This is the servo box
        difference() {
            cube([servoBodySupport, 12 + 1 + shellThickness, 22.2 + 1 + shellThickness], center = true);
            cube([servoBodySupport, 12 + 1, 22.2 + 1], center = true);

            //Servo cable slot
            translate([0, 0, -2 * eccentricity]) cube([100, 3, 3], center = true);

        }

    }

}

//--------------------------------
module box(Xdim, Ydim, Zdim, thickness, application)
    //Creates a box, dimensions are internal
    {
        difference() {

            cube([Xdim + thickness, Ydim + thickness, Zdim], center = true);
            translate([0, 0, thickness / 2]) cube([Xdim, Ydim, Zdim], center = true);
            if (application == "servo") {
                translate([-Xdim / 2, 0, -0.5 * Zdim]) cube([5, Ydim + 2 * thickness, Zdim / 2 + thickness], center = true);
                translate([+Xdim / 2, 0, -0.5 * Zdim]) cube([5, Ydim + 2 * thickness, Zdim / 2 + thickness], center = true);
                translate([+Xdim / 2, 0, 0]) cube([thickness / 2, 0.3 * Ydim, Zdim], center = true);
                translate([-Xdim / 2, 0, 0]) cube([thickness / 2, 0.3 * Ydim, Zdim], center = true);
            }
        }
    }

//Baseplate for pan mechanism
module base(servo) {
        difference() {

            {
                minkowski() {
                    cylinder(r = R + mik, h = supportBaseHeight);
                    rotate([90, 0, 0]) cylinder(r = mik, h = 1);
                }

                //This to create a anchoring mechanism with the pan base
                //translate([0, 0,-mik])cylinder(r = R + mik+3, h = 2);
            }
            if (servo == true) {
                translate([0, 0, -supportZ - servoHornThickness - mik]) rotate([0, 90, 0]) servoHorn("cross");
                cylinder(r = 2.5, h = 15, center = true);
            }
        }
    }

module supportSection() {
        intersection() {
            difference() {
                sphere(R);
                cube([gimballWidth, 2 * gimballWidth, 2 * gimballWidth], center = true);

            }
            translate([R - supportX / 2, 0, 0]) cube([supportX, supportY, 10], center = true);
        }
    }
    //-------------------------

    //This creates the supporting pillar for the camera shell
    module tiltSupport()

    {
        union() {
            difference() {
                sphere(R);
                cube([gimballWidth, 2 * gimballWidth, 2 * gimballWidth], center = true);
                translate([-gimballWidth, 0, 0]) cube([2 * gimballWidth, 2 * gimballWidth, 2 * gimballWidth], center = true);

            }

            hull() {
                translate([0, 0, -5]) supportSection();
                translate([0, 0, -supportZ]) supportSection();
            }
        }

    }

module servoTiltSupport(xPos, Pos) {
    //The module ned to be rewritten to be easy to read!!!
        //Need to center the servo shaft, the second figure is the distance form border
        supportPosition = xPos;
        //Need to adjust the clearance to account for the Xpos
        supportCurvature = 30;

        rotate([-0, 0, 0]) difference() {

            union() {

                difference() {
                    translate([-shellThickness / 2 + supportPosition, 0, 0]) {
                        cube([shellThickness, 30, 1.8 * RatX(gimballWidth / 2)], center = true);
                    }

               difference(){sphere(5*R);sphere(R - shellThickness);}
                       difference() {
                        }
                    }

                translate([-servoBodySupport / 2 + supportPosition, 0, eccentricity]) {
                    //This is the servo box
                     difference() {
                        cube([servoBodySupport, 12 + tolerance + shellThickness + 3 , 22.2 + 3 + shellThickness], center = true);
                        cube([servoBodySupport, 12 + tolerance, 22.2 + 1.1*tolerance], center = true);

                        //Servo cable slot
                        translate([0, 0, -2 * eccentricity]) cube([100, 4, 4], center = true);

                    }

                }
            }

            //This is the slot in the servo arm
            translate([servoClerance + 8 + shellThickness, 0, eccentricity]) {
                cube([20 + tolerance, 12 + tolerance, 32.2 ], center = true);
                translate([-31 / 2, 0, 0]) cube([31 + 1, 12, 22.2 + + 1.1*tolerance], center = true);

            }
        }

        //This is the curved extra support for the connection with the gimball internal shell
             translate([0, 0, 0])SUB_tiltwedge(xPos);
             mirror([0,0,1])translate([0, 0, 0])SUB_tiltwedge(xPos);

    }

    //-------------------------

module SUB_tiltwedge(xPos) {
   supportCurvature = 30;

            difference() {
                translate([12, 0, +RatX(xPos) - 10])
                difference() {
                    cube([16, 30, 50], center = true);
                    translate([-supportCurvature, 0, -supportCurvature]) sphere(r = supportCurvature + 20, center=true);

                }

                difference() {
                    sphere(10*R);

                    sphere(R - shellThickness);

                }

            }

}

module cameraSupport() {
        difference() {
            difference() {
                sphere(R);
                sphere(R - shellThickness);
            }

            translate([R + gimballWidth / 2, 0, 0]) cube([2 * R, 2 * R, 2 * R], center = true);
            translate([-R - gimballWidth / 2, 0, 0]) cube([2 * R, 2 * R, 2 * R], center = true);
            //Creates camera support
            translate([0, R - 7, 0]) cube([PIcameraX + tolerance, 3, PIcameraY + tolerance], center = true);
            translate([0, R - 7, 0]) cube([2, 3, PIcameraY], center = true);
            //Slot for camera wires
            translate([0, R - 8, -PIcameraY / 2 - 2]) cube([PIcameraX - 5, 3, 3], center = true);

            //Hole for the camera
            translate([0, R, 0]) rotate([90, 0, 0]) cube([PIcameraDiam + tolerance, 10, PIcameraDiam + tolerance], center = true);
		translate([0,0.9*R,0])SUB_PiCamHoles(0.3);

            }

        //Need to hardwire the servo dimensions

        {
            servoTiltSupport(gimballWidth/2, "tilt");

        }
        //Pivot mechanism. Need to understand why 0.98 otherwise a layer gets created
        translate([-gimballWidth / 2, 0, 0]) {
            difference() {
                rotate([0, 90, 0]) cylinder(r = panSupport, h = 0.98*shellThickness);
                gimballPivot(1);
                rotate([0, 90, 0]) cylinder(r = gimballPivotR - shellThickness, h = shellThickness);

            }
            gimballPivot(1);
        }
    }

    //-------------------------

module SUB_PiCamHoles(T) {
// T is the tolerance for holes
        translate([PIcameraX/2-2, 0, PIcameraY/2-2])rotate([90,0,0])cylinder(r=1+T,h=10, center=true);
		translate([-(PIcameraX/2-2), 0, PIcameraY/2-2])rotate([90,0,0])cylinder(r=1+T,h=10, center=true);
		translate([PIcameraX/2-2, 0, (PIcameraY/2-2)-12.5])rotate([90,0,0])cylinder(r=1+T,h=10, center=true);
		translate([-(PIcameraX/2-2), 0, (PIcameraY/2-2)-12.5])rotate([90,0,0])cylinder(r=1+T,h=10, center=true);

}

module camBolt() {
    difference(){
         SUB_camBoltFrame();
        SUB_PiCamHoles(0.1);

}
}

module SUB_camBoltFrame(){

translate([PIcameraX/2-2,0,PIcameraY/2-2])rotate([90,0,0])cylinder(r=3,h=8, center=true);
translate([-(PIcameraX/2-2),0,PIcameraY/2-2])rotate([90,0,0])cylinder(r=3,h=8, center=true);
translate([-(PIcameraX/2-2),0,+(PIcameraY/2-2)-12.5])rotate([90,0,0])cylinder(r=3,h=8, center=true);
translate([(PIcameraX/2-2),0,+(PIcameraY/2-2)-12.5])rotate([90,0,0])cylinder(r=3,h=8, center=true);
translate([0,+2.5-4,0]){
    translate([0,0,(PIcameraY/2-2)-12.5])cube([(PIcameraX-2),5,5], center=true);
translate([0,0,(PIcameraY/2-2)])cube([(PIcameraX-2),5,5], center=true);
translate([PIcameraX/2-2.5,0,12.5/2])cube([5,5,(12.5)], center=true);
translate([-(PIcameraX/2-2.5),0,12.5/2])cube([5,5,(12.5)], center=true);
}

}

module servoHorn(type) {
        cube([servoHornThickness, servoHornWidth, servoHornLenght], center = true);
        if (type == "cross") rotate([90, 0, 0]) cube([servoHornThickness, servoHornWidth, servoHornLenght], center = true);
    }
    //-------------------------

module gimballPivot(tolerance) {
        rotate([0, 90, 0])
        difference() {
            cylinder(r = gimballPivotR - tolerance / 2, h = gimballPivotR / 2, center = true);
            cylinder(r = gimballPivotR - 3 + tolerance / 2, h = gimballPivotR / 2, center = true);
        }
    }
    //-------------------------

module support() {
    scaleFactor = (R + tolerance) / R;

    difference() {
        tiltSupport();

        translate([gimballWidth / 2 + servoHornThickness / 2, 0, 0]) rotate([45, 0, 0]) servoHorn("line");
        translate([gimballWidth / 2, 0, 0]) rotate([0, 90, 0]) cylinder(r = 3, h = 30);

    }

    //Need to cut holes in the base for servo and camera cables and the screws
    translate([0, 0, -supportBaseHeight / 2])
    difference() {

        {
            color("blue", 0.5) translate([0, 0, -supportZ - supportBaseHeight]) base(true);
            translate([0, 0, -supportZ - servoHornThickness]) rotate([0, 90, 0]) servoHorn("cross");
            SUB_cameracableDuct();
            translate([0, 0, +supportBaseHeight / 2]) mirror([1, 0, 0]) tiltSupport();
            SUB_mountedPillarScrewHoles();
            translate([-gimballWidth / 2 - supportX / 2, 0, 0]) rotate([0, 0, 180])
            SUB_servocableDuct();

        }

    }

}

module mountedPillar() {
    //Pillar for camera. This one needs to be mounted separately
    difference() {
        mirror([1, 0, 0]) tiltSupport();
        translate([-gimballWidth / 2, 0, 0]) gimballPivot(0);
        translate([-gimballWidth / 2, 0, 0]) gimballPivot(3); {
            SUB_cameracableDuct();
            SUB_mountedPillarScrewHoles();
            translate([-gimballWidth / 2 - supportX / 2, 0, -supportX / 2]) rotate([0, 0, 180])
            SUB_servocableDuct();
        }

    }

}

module SUB_screw(tolerance) {
    cylinder(r = screwDiam / 2 + tolerance, h = screwLenght);
    translate([0, 0, -3]) cylinder(r = 2 * screwDiam / 2 + screwTolerance, h = 4);
}

module SUB_mountedPillarScrewHoles() {
    color("blue", 0.5) translate([-R + supportX / 2 + 2, 0, -supportZ - screwLenght / 2]) {
        translate([0, 0.5 * panSupport, 0]) SUB_screw(-screwTolerance);
        mirror([0, 1, 0]) translate([0, 0.5 * panSupport, 0]) SUB_screw(-screwTolerance);
    }
}

module SUB_servocableDuct() {
    //Duct for servo cable
    {
        translate([0, 0, -supportZ + supportX]) cylinder(r = supportX / 3, h = supportZ + supportX / 2, center = true);
        translate([-supportX, 0, 0]) rotate([0, 120, 0]) cylinder(r = supportX / 3, h = supportX, center = false);
        translate([0, 0, -supportZ - supportX / 3]) rotate([0, 90, 180]) cylinder(r = supportX / 3, h = 0.6 * R, center = false);
    }

}

module SUB_cameracableDuct() {
        //Duct for camera connetion
        translate([-gimballWidth / 2 - 0.5 * supportX, 0, 0]) rotate([0, 0, 90]) {
            translate([0, 0, 0]) rotate([90, 0, 0]) cylinder(r = 26 / 2, h = 0.6 * supportX);
            translate([0, 0, -supportZ / 2]) cube([20, 3, supportZ + 1.1 * supportBaseHeight], center = true);
            translate([0, -R * 0.5 + 13, -supportZ - supportBaseHeight]) rotate([90, 0, 0]) cube([20, 5, R * 0.5], center = true);

        }
    }
    //---------------------------

module connectionSocket() {

    cylinder(r = 3, h = 5);
    translate([-9, -3 / 2, 0]) cube([10, 3, 5]);

}

module PiSupport() {
    difference() {
        translate([0,0,1])cube([4 + 3 / 2 - 0.4, 4 + 3 / 2 - 0.2, 8], center = true);
        cylinder(r = 3 / 2 - 0.2, h = 2 * Piheight + 8, $fs = 0.1);
    }

}

module case () {
    translate([0, 0, -boxHeight / 2 - supportZ - 2 * supportBaseHeight]) {
        difference() {
            minkowski() {
                box(boxLength, boxDepth, boxHeight, boxThickness, "PI");
                //sphere(r = mik);
                cylinder(r = mik, h = 2);
            }
            translate([R - 10, -Piwidth / 2, -boxHeight / 2 - 5 / 2]) connectionSocket();
            translate([-R + 10, -Piwidth / 2, -boxHeight / 2 - 5 / 2]) connectionSocket();
            translate([R - 10, Piwidth / 2, -boxHeight / 2 - 5 / 2]) connectionSocket();
            translate([-R + 10, Piwidth / 2, -boxHeight / 2 - 5 / 2]) connectionSocket();

            translate([0, 0, -boxHeight / 2 - 5 / 2]) cylinder(r = 3, h = 5);

translate([-Pilength / 2, -16, -boxHeight / 2 + 5 + shellThickness]) {
                rpi();
            }
//This is the power inlet. The +6 in z is half the z-lenght of the component
translate([-boxLength/2,-boxDepth/2+8,-boxHeight/2+shellThickness+2*mik+tolerance])cube([15+tolerance,9+tolerance,12], center=true);

        }
        translate([-Pilength / 2, -16, -boxHeight / 2 + 1 + shellThickness]) {
translate ([Pilength-3.5, Piwidth-3.5,-0.1]) PiSupport();
translate ([Pilength-3.5, -0+3.5,-0.1]) PiSupport();
translate ([Pilength-58-3.5, Piwidth-3.5,-0.1]) PiSupport();
translate ([Pilength-58, 0+3.5,-0.1]) PiSupport();
          //translate([25.5, 18, 0]) PiSupport();
            //translate([Pilength - 5, Piwidth - 12.5, 0]) PiSupport();

        }

    }
translate([-boxLength/2+15/2+mik,-boxDepth/2+8,-supportZ-boxHeight-4])rotate([0,0,180])SUB_Power();

}

module topLid() {
    tolerance = 0.02;

    difference() {
        difference() {
            {
                minkowski() {
                    translate([0, 0, -supportZ - supportBaseHeight - topCoverHeight / 2]) cube([boxLength + mik - 1, boxDepth + mik - 1, topCoverHeight], center = true);
                    sphere(r = mik); //cylinder(r = mik, h = 2);
                }
                translate([0, 0, -supportZ - supportBaseHeight]) {
                    scale([1 + tolerance, 1 + tolerance, 1]) base("false");
                    scale([0.9, 0.9, 30]) base("false");

                    //This is the grid an hole for mic.need to re-work the placement definition as it will not work for other box dimensions!!!
                    translate([boxLength / 2 - 5 - mik - boxThickness, -(boxDepth / 2 - 5 - mik - boxThickness), +14 - supportBaseHeight - topCoverHeight / 2]) rotate([0, 180, 0]) SUB_Mic();

                }

            }

        }

        scale([0.98,0.98,1])case ();

    }

//Need to explain the -1.4*supportBaseHeight
difference(){
translate([0,0,-supportZ-1.4*supportBaseHeight])rotate([0,-90,90])testSupport();
       case ();

}

}

module SUB_Mic() {
    translate([-7, 0, 0]) for (i = [1: 6]) {
        translate([i * 2, 0, 0]) cube([1, 10, 2], center = true);
    }
    cylinder(r = 5, h = 2 * topCoverHeight);

}

module SUB_Power(){
	difference(){
		cube([15,9+3,12], center=true);
		translate([2,0,2])cube([15+tolerance,9+tolerance,12], center=true);
	}
}
module assembly(view)
{

space = (view == "explode") ? 20 : 0;

translate([-space,0,0])cameraSupport();
translate([0,0,-space])support();
translate([-3*space,0,0])mountedPillar();
translate([0,0,-3*space])topLid();

//translate([0,0,-4*space-1.5*supportZ])panSupport();
translate([0,0,-6*space])case ();

}

//-------------------------------
module testSupport(xPos, Pos) {
        //Need to center the servo shaft, the seconf figure is the distance form border
        eccentricity = 22.2 / 2 - 5;
        servoBodySupport = 25;
        //Need to adjust the clearance to account for the Xpos
		armLenght = 1.4*(boxDepth/2);
       difference() {

            union() {

                difference() {
                    translate([-shellThickness / 2, 0, 15]) {
                        cube([shellThickness, servoBodySupport, armLenght], center = true);
                    }

                }

                translate([-servoBodySupport / 2, 0, eccentricity]) {
                    //This is the servo box
                    difference() {
                        cube([servoBodySupport, 12 + 1 + shellThickness, 22.2 + 1 + shellThickness], center = true);
                        cube([servoBodySupport, 12 + 1, 22.2 + 1], center = true);

                        //Servo cable slot
                        translate([0, 0, -2 * eccentricity]) cube([100, 4, 4], center = true);

                    }

                }
            }

            //This is the slot in the servo arm. Need to check why -15 in the translate is needed
translate([-(11)+(32.2/2+12/2+tolerance/2)-15, 0, eccentricity]) {

                cube([20 + tolerance, 12+tolerance/2, 32.2 + tolerance], center = true);
                translate([-31/2, 0, 0]) cube([31 + tolerance, 12+tolerance/2, 22.2 + tolerance], center = true);

            }

}

//Dimensions are hardwired, should be parameters!!!
		translate([-10,0,+armLenght/2+15])rotate([270,0,0])linear_extrude(height = servoBodySupport, center = true, convexity = 10, twist = 0)
			//polygon([[0,0],[8,20],[10,0]], convexity = N);
 polygon([[0,0],[10,armLenght/3],[10,0]], convexity = N);

}

//-------------------------

assembly("explode");
//case();
//topLid();
//SUB_Power();

//mountedPillar();

//servoTiltSupport(gimballWidth/2, "tilt");

//cameraSupport();
//support();
//camBolt();


initial design.  checking in before changing a bit

// unified payload electronics mount

Bhole=2.38+.2;  // for brass tube
PCBhole = (25.4*3/32)/2;//1;  // found that 3/32" drill made good pilot for #4 self-piloting screw
include <JansenDefs.scad>;  // Bx
layer1bias = 0.4;
platformHeight = 45; // from bar to top platform
mountHeight=15; // from bar to electronics platform
PCBwidth=43;
HoleInset=3;

thick=5;
t2=thick/2;

sf = 16;  // sphere faces

difference() {
   payloadMount(Bx,Bhole,PCBwidth,HoleInset,PCBhole);

   #for(x=[-1,1]) translate([x*Bx,0,-1]) cylinder(r=Bhole,h=44,$fn=25);
   translate([0,0,-4]) cube([200,200,8],center=true);
}

//translate([0,20,0]) L298mount();

thinWall=0.41;  // width of thinnest wall which will not get culled by slicer

module L298mount() intersection() { cube([99,99,4],center=true);

  difference() {
    union() {
      hull() {
        cube([36,1,4],center=true);
        for(x=[-1,1]) translate([x*27,17,0])
          scale([5,5,3]) sphere(1,$fn=24);
      }
    }

    translate([0,20,0]) scale([16,11,4]) sphere(1,$fn=60);

    difference() {
      union() {
        //%scale([6,3,4]) sphere(1,$fn=36);

        for(x=[-1,1]) {
          translate([x*(PCBwidth/2-HoleInset),18,-4])
            #cylinder(r=PCBhole,h=9,$fn=15);

          translate([x*27,17,-4]) cylinder(r=1.6,h=9,$fn=15);
          translate([x*16,8,-4]) rotate([0,0,30]) cylinder(r=1.5,h=9,$fn=6);
          translate([x*23,10,-4]) rotate([0,0,30]) cylinder(r=2,h=9,$fn=6);
          translate([x*20.5,6,-4]) rotate([0,0,30]) cylinder(r=1.5,h=9,$fn=6);
          translate([x*17,4,-4]) rotate([0,0,30]) cylinder(r=1.5,h=9,$fn=6);
          translate([x*13,5,-4]) rotate([0,0,30]) cylinder(r=1.5,h=9,$fn=6);
          translate([x*9,4,-4]) rotate([0,0,30]) cylinder(r=2,h=9,$fn=6);
          translate([x*5,4,-4]) rotate([0,0,30]) cylinder(r=1.5,h=9,$fn=6);
        }
      }
      %cube([99,99,thinWall],center=true); // leave support wall
    }
  }
}

module payloadMount(axisSep,axisRad,platWidth,dHole,rHole) {
  //difference() {
    union() {
      //%braceBar(axisSep,axisRad);
      for (x=[-1,1]) hull() {
        translate([x*axisSep,0,0])
           cylinder(r1=axisRad+3,r2=axisRad+2,h=12,$fn=36);
        translate([x*(axisSep-14),0,0]) cylinder(r=0.4,h=1,$fn=4);
      }
      hull() {
        translate([0,5,2]) cube([2*axisSep,.5,4],center=true);
        cube([2*axisSep,1,1],center=true);
      }

      translate([0,-34,0]) rotate([90,0,0]) L298mount();

      for(x=[-1,1]) hull() {  // main side braces
        translate([x*axisSep,0,5]) scale([.6,.6,4]) sphere(1,$fn=16);
        translate([x*axisSep,0,0]) cube([2,2,1],center=true);
        translate([x*18,-34,0]) cube([4,4,1],center=true);
        translate([x*27,-34,8]) sphere(0.6,$fn=12);
      }

      *for(x=[-1,1]) hull() {  // secondary supports
        translate([x*1 , 4 ,0.5]) scale([3,1,1]) sphere(1,$fn=16);
        translate([x*16,-34,0.5]) scale([2,1,1]) sphere(1,$fn=16);
      }

    }
  //}
}

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


move refactor

move refactor

module dotstarMatrixTixClockPlate()
{
    difference()
    {
        xLength = dotstarMatrixTixClockPlate_xLength();
        yLength = dotstarMatrixTixClockPlate_yLength();

        cube([xLength, 23, 1]);

        dotstarMatrixTixClockPlate_cutouts();
    }
}

module dotstarMatrixTixClockPlate_cutouts(plateLength_x, plateLength_y)
{
    plateLength_x = dotstarMatrixTixClockPlate_xLength();
    plateLength_y = dotstarMatrixTixClockPlate_yLength();

    cutoutLengthX = dotstarMatrixTixClockPlate_cutouts_xLength();
    cutoutLengthY = dotstarMatrixTixClockPlate_cutouts_yLength();

    xTranslate = dotstarMatrixTixClockPlate_cutouts_hourTens_xTranslate();
    yTranslate = dotstarMatrixTixClockPlate_cutouts_hourTens_yTranslate();

    echo("yt:", yTranslate);

    // hour tens cutout
    translate([xTranslate, yTranslate, -0.01])
    cube([cutoutLengthX, cutoutLengthY, 1.02]);

    // hour ones cutout
//    dotstarMatrixTixClockPlate_cutouts_hourOnes();
}

module dotstarMatrixTixClockPlate_cutouts_hourOnes()
{
    xTranslate = dotstarMatrixTixClockPlate_cutouts_hourTens_xTranslate()
                 + dotstarMatrixTixClockPlate_cutouts_xLength() * 2;

    yTranslate = dotstarMatrixTixClockPlate_cutouts_hourTens_yTranslate();

    cutoutLengthX = dotstarMatrixTixClockPlate_cutouts_xLength();
    cutoutLengthY = dotstarMatrixTixClockPlate_cutouts_yLength();

    translate([xTranslate, yTranslate, -0.01])
    cube([cutoutLengthX, cutoutLengthY, 1.02]);

}

function dotstarMatrixTixClockPlate_xLength() = 50;

function dotstarMatrixTixClockPlate_yLength() = 23;

function dotstarMatrixTixClockPlate_cutouts_xLength() = 2.6;

function dotstarMatrixTixClockPlate_cutouts_yLength() = 18;

function dotstarMatrixTixClockPlate_cutouts_hourTens_xTranslate() = 7;

function dotstarMatrixTixClockPlate_cutouts_hourTens_yTranslate() = (dotstarMatrixTixClockPlate_yLength() - dotstarMatrixTixClockPlate_cutouts_yLength()) / 2.0;

module dotstarMatrixTixClockPlate()
{
    difference()
    {
        xLength = dotstarMatrixTixClockPlate_xLength();
        yLength = dotstarMatrixTixClockPlate_yLength();

        cube([xLength, 23, 1]);

        dotstarMatrixTixClockPlate_cutouts();
    }
}

module dotstarMatrixTixClockPlate_cutouts(plateLength_x, plateLength_y)
{
    plateLength_x = dotstarMatrixTixClockPlate_xLength();
    plateLength_y = dotstarMatrixTixClockPlate_yLength();

    cutoutLengthX = 2.6;
    cutoutLengthY = 18;

    xTranslate = 7;
    yTranslate = (plateLength_y - cutoutLengthY) / 2.0;

    echo("yt:", yTranslate);

    // hour tens cutout
    translate([xTranslate, yTranslate, -0.01])
    cube([cutoutLengthX, cutoutLengthY, 10.02]);

    // hour ones cutout
    dotstarMatrixTixClockPlate_cutouts_hourOnes(cutoutLengthX = cutoutLengthX, cutoutLengthY = cutoutLengthY);
}

module dotstarMatrixTixClockPlate_cutouts_hourOnes(cutoutLengthX, cutoutLengthY)
{

}

function dotstarMatrixTixClockPlate_xLength() = 50;

function dotstarMatrixTixClockPlate_yLength() = 23;


The customizer verson was corrected.

The customizer verson was corrected.

use <../coins-pendants-ornaments.scad>

/* [General] */
height = 3; // [1:10]
includeGimbal = "yes"; // [yes, no]

/* [Inner Icon] */
innerIcon = "Tree"; // [Tree, Cross, Throwie, Star of David, Crescent Star, Star, Blue Moon, Clover, Heart, Horseshoe, Hourglass, OSHW, Texas, Africa, Oval, Balloon, Circle]
innerIconXyScale = 1.15; // [-1 : 0.05 : 30]
innerIconOffsetY = -13; // [-35:35]

/* [Outer Icon] */
outerIcon = "Tree"; // [Tree, Cross, Star of David, Crescent Star, Star, Blue Moon, Clover, Heart, Horseshoe, Hourglass, OSHW, Texas, Africa, Oval, Balloon, Circle]
outerIconXyScale = 0.4; // [-1 : 0.05 : 25]
outerIconCount = 8; // [1:15]

/* [Hidden] */

$fn=100;

ornament(height = height,
         includeGimbal = includeGimbal,
         innerIcon = innerIcon,
         innerIconXyScale = innerIconXyScale,
         innerIconOffsetY = innerIconOffsetY,
         outerIcon = outerIcon,
         outerIconXyScale = outerIconXyScale,
         outerIconCount = outerIconCount);

//
// This OpenScad script generates coins, pendants, and ornaments.
//
// Author: Roberto Marquez - http://electronics.onebeartoe.org/
//
// This OpenSCAD script is a derivative of:
//
// Customizable Gimbal v1.0
// by TheNewHobbyist 2014 (http://thenewhobbyist.com)
// http://www.thingiverse.com/thing:340948
// https://github.com/thenewhobbyist/OpenSCAD/tree/master/Customizable%20Gimble
//
// "Customizable Gimbal" as well as this script are licensed under a
// Creative Commons Attribution-NonCommercial 3.0 Unported License.
//
// TheNewHobbyist's Inspiration and attribution:
//
// Printrbot Gimbal by DesignMakeTeach
// http://www.thingiverse.com/thing:317778
// Licensed under the Creative Commons - Attribution - Share Alike license.
//
// Stencil-o-Matic by Benjamin
// http://www.thingiverse.com/thing:55821
// Licensed under the Creative Commons - Attribution - Non-Commercial license.

/* [General] */
height = 3; // [1:10]
includeGimbal = "yes"; // [yes, no]

/* [Inner Icon] */
innerIcon = "Tree"; // [Tree, Cross, Throwie, Star of David, Crescent Star, Star, Blue Moon, Clover, Heart, Horseshoe, Hourglass, OSHW, Texas, Africa, Oval, Balloon, Circle]
innerIconXyScale = 1.15; // [-1 : 0.05 : 30]
innerIconOffsetY = -13; // [-35:35]

/* [Outer Icon] */
outerIcon = "Tree"; // [Tree, Cross, Star of David, Crescent Star, Star, Blue Moon, Clover, Heart, Horseshoe, Hourglass, OSHW, Texas, Africa, Oval, Balloon, Circle]
outerIconXyScale = 0.4; // [-1 : 0.05 : 25]
outerIconCount = 8; // [1:15]

/* [Hidden] */

$fn=100;

ornament(height = height,
         includeGimbal = includeGimbal,
         innerIcon = innerIcon,
         innerIconXyScale = innerIconXyScale,
         innerIconOffsetY = innerIconOffsetY,
         outerIcon = outerIcon,
         outerIconXyScale = outerIconXyScale,
         outerIconCount = outerIconCount);

module ornament(height = 3,
                includeGimbal = "yes", // [yes, no]
                innerIcon = "Tree",
                innerIconXyScale = 0.9,
                innerIconOffsetY = -4,
                outerIcon = "Tree",
                outerIconXyScale = 0.2,
                outerIconCount = 10)
{
    {
        coinScale =  0.2;//0.199248

        union()
        {
            if(includeGimbal == "yes")
            {
                ring1(height);
                ring2(height);
                ring3(height);

                xyScale = 0.5;
                zTranslate = -height / 2.0;
                translate([0, -22, zTranslate])
                scale([xyScale, xyScale, 1])
                openCylinder(center=true);
            }

            difference()
            {
                color("blue")
                scale([coinScale, -coinScale, 1])
                coin(innerIcon = innerIcon,
                     innerIconXyScale = innerIconXyScale,
                     innerIconOffsetY = innerIconOffsetY,
                     outerIcon = outerIcon,
                     outerIconCount = outerIconCount,
                     outerIconXyScale = outerIconXyScale,
                     radius = 55,
                     height=height
                );

                clipOversizedImages(center=true);
            }
        }
    }
}

module clipOversizedImages()
{
	difference()
	{
		cylinder(r=200, h=10, center=true);
		cylinder(r=11, h=11, center=true);
	}
}

module ring1(height)
{
	difference()
	{
	    color("pink")
    	cylinder(r=19.35, h=height, center=true);

    	cylinder(r=17.35, h=56, center=true);
    	translate([17.45,0,0]) rotate([0,90,0]) cylinder(r1=1.7, r2=0, h=2.1, center=true);
    	translate([-17.45,0,0]) rotate([0,270,0]) cylinder(r1=1.7, r2=0, h=2.1, center=true);
	}
}

module ring2(height)
{
	translate([16.95,0,0]) rotate([0,90,0]) cylinder(r1=1.7, r2=0, h=2.1, center=true);
	translate([-16.95,0,0]) rotate([0,270,0]) cylinder(r1=1.7, r2=0, h=2.1, center=true);
	difference()
	{
	    color("grey")
		cylinder(r=15.95, h=height, center=true);

		cylinder(r=13.95, h=56, center=true);
		translate([0,-14.2,0]) rotate([90,0,0]) cylinder(r1=1.7, r2=0, h=2.1, center=true);
		translate([0,14.2,0]) rotate([270,0,0]) cylinder(r1=1.7, r2=0, h=2.1, center=true);
	}
}

module ring3(height)
{
	translate([0,13.75,0]) rotate([270,0,0]) cylinder(r1=1.7, r2=0, h=2.1, center=true);
	translate([0,-13.75,0]) rotate([90,0,0]) cylinder(r1=1.7, r2=0, h=2.1, center=true);
	difference()
	{
		cylinder(r=12.75, h=height, center=true);
		cylinder(r=10.75, h=56, center=true);
	}
}

// Below this comment are the modules for the various charms.

module coin(innerIcon,
            innerIconXyScale,
            innerIconOffsetY,
            outerIcon,
            outerIconCount,
            outerIconXyScale,
            radius,
            height)
{
    difference()
    {
        // main disk
        cylinder (h = height, r=radius, center = true, $fn=100);

        // inner icon
        translate([0, innerIconOffsetY, -5])
        scale([innerIconXyScale, innerIconXyScale, 6.5])
        coinIcon(innerIcon, height);

        // outer icons
        for ( i = [0 : outerIconCount] )
        {
            rotate( i * 360 / (outerIconCount+1), [0, 0, 1])
            translate([0, 43, -5])
            scale([outerIconXyScale, outerIconXyScale, 3.0])
            coinIcon(outerIcon, height);
        }
    }
}

module coinIcon(iconName, height)
{
    if(iconName == "Cross")
    {
        crucifixionCcross(height);
    }
    else if(iconName == "Throwie")
    {
        throwieCutout(height=height);
    }
    else if(iconName == "Star of David")
    {
        starOfDavid();
    }
    else if(iconName == "Crescent Star")
    {
        crescentStar();
    }
    else if(iconName == "Star")
    {
        star(height);
    }
    else if(iconName == "Blue Moon")
    {
        blueMoon();
    }
    else if(iconName == "Clover")
    {
        clover();
    }
    else if(iconName == "Heart")
    {
        heart();
    }
    else if(iconName == "Horseshoe")
    {
        horseshoe();
    }
    else if(iconName == "Hourglass")
    {
        hourglass();
    }
    else if(iconName == "OSHW")
    {
        oshwlogo800px();
    }
    else if(iconName == "Texas")
    {
        texas();
    }
    else if(iconName == "Africa")
    {
        africa();
    }
    else if(iconName == "Oval")
    {
        oval();
    }
    else if(iconName == "Balloon")
    {
        balloon();
    }
    else if(iconName == "Circle")
    {
        disk();
    }
    else
    {
        // defalut
        christmasTree(height);
    }
}

module openCylinder(height = 3)
{
    difference()
    {
        cylinder(r=7, h=height);

        radius = 4.5;
        translate([0, 0, -1])
        cylinder(r=radius, h=height+2);
    }
}

module africa(h=3)
{
  scale([25.4/90, -25.4/90, 1]) union()
  {
    linear_extrude(height=h)
      polygon([[-150.580000,-277.423125],[-146.079531,-276.225156],[-140.091250,-275.406875],[-134.097344,-275.194219],[-129.580000,-275.813125],[-120.055000,-280.393125],[-114.524688,-282.987813],[-108.580000,-284.883125],[-90.580000,-286.663125],[-82.580000,-285.883125],[-75.580000,-286.763125],[-62.580000,-286.763125],[-52.580000,-288.703125],[-50.015000,-281.841875],[-49.666250,-278.301094],[-50.600000,-274.703125],[-52.933750,-271.236875],[-54.930000,-267.703125],[-55.193555,-265.725156],[-54.839063,-264.181250],[-52.785000,-262.050625],[-46.860000,-259.203125],[-41.540000,-255.233125],[-36.507344,-253.268438],[-31.121250,-252.310625],[-25.977031,-251.574063],[-21.670000,-250.273125],[-17.605000,-247.005625],[-13.570000,-243.123125],[-8.228750,-240.278125],[-2.580000,-238.243125],[5.116250,-234.408125],[9.233906,-233.020312],[13.330000,-233.033125],[16.578496,-234.635938],[18.767969,-237.296250],[21.523750,-244.195625],[22.867012,-247.637813],[24.705156,-250.543750],[27.426660,-252.515000],[31.420000,-253.153125],[34.020625,-252.561875],[37.112500,-251.273125],[43.420000,-248.613125],[54.744844,-245.195000],[66.751250,-242.238125],[72.823418,-241.322891],[78.842031,-240.991250],[84.732441,-241.399297],[90.420000,-242.703125],[92.335469,-239.300469],[94.096250,-237.531875],[96.518906,-236.848906],[100.420000,-236.703125],[101.106250,-239.456875],[102.850000,-241.663125],[105.623281,-242.223437],[109.931250,-242.088125],[114.233594,-241.457812],[116.990000,-240.533125],[118.950313,-237.889844],[119.937500,-234.041875],[120.058437,-229.982031],[119.420000,-226.703125],[116.170000,-232.609375],[114.042500,-235.172969],[111.420000,-237.413125],[109.258437,-238.469219],[107.140000,-238.586875],[105.336562,-237.645156],[104.120000,-235.523125],[104.051445,-233.774590],[104.660937,-231.706719],[107.225000,-227.049375],[112.910000,-218.703125],[117.230000,-209.703125],[129.190000,-193.703125],[136.070000,-179.703125],[143.770000,-170.703125],[145.389180,-167.818691],[146.422187,-164.894531],[147.452500,-159.011875],[148.306562,-153.224844],[150.430000,-147.703125],[153.026562,-144.378281],[155.977500,-141.654375],[158.977187,-138.954844],[161.720000,-135.703125],[163.706875,-131.857500],[165.367500,-127.753125],[167.901875,-123.198750],[172.510000,-118.003125],[196.360000,-99.413125],[198.547500,-96.899375],[199.119062,-95.462969],[199.190000,-93.703125],[198.023750,-88.798125],[197.858281,-85.915312],[199.190000,-83.293125],[202.035000,-81.735625],[205.420000,-80.643125],[210.616250,-78.339375],[216.420000,-77.033125],[221.343438,-77.255469],[226.137500,-78.466875],[235.420000,-81.903125],[242.420000,-83.823125],[247.420000,-86.313125],[252.815000,-87.886875],[261.420000,-91.703125],[260.857031,-82.415469],[259.203750,-75.181875],[252.840000,-59.703125],[248.200156,-48.958594],[243.043750,-38.299375],[237.105469,-28.092031],[230.120000,-18.703125],[214.420000,-3.703125],[202.590000,8.296875],[190.130000,23.296875],[182.700000,31.296875],[180.686719,34.408750],[179.621250,37.066875],[178.775156,39.537500],[177.420000,42.086875],[174.637500,45.061875],[171.990000,48.396875],[170.576719,52.960156],[170.493750,57.768125],[171.990000,67.296875],[173.087500,77.353125],[174.860000,87.296875],[176.987344,92.743437],[178.753750,95.896875],[179.963281,99.500312],[180.420000,106.296875],[180.420000,128.296875],[180.215000,134.388125],[179.604375,137.343281],[178.330000,140.126875],[175.454687,143.364688],[171.535000,146.326875],[163.420000,151.146875],[147.795000,161.195625],[139.491250,167.401719],[134.150000,172.586875],[132.644941,175.943496],[132.273906,179.825469],[133.563750,188.533125],[135.279219,197.445156],[135.440215,201.582598],[134.680000,205.296875],[133.025547,208.148828],[130.675000,210.429375],[124.757500,213.874375],[118.671250,216.828125],[116.109766,218.494609],[114.160000,220.486875],[112.725937,224.129219],[112.152500,228.723125],[111.327812,234.151406],[109.140000,240.296875],[106.635625,244.352031],[103.805000,247.665625],[97.630000,254.306875],[87.605312,266.389844],[82.611602,271.620801],[77.350000,276.165625],[71.610273,279.914980],[65.182187,282.759531],[57.855508,284.589941],[49.420000,285.296875],[37.996250,285.775625],[27.420000,287.716875],[21.231250,288.703125],[18.320156,288.421406],[15.440000,286.966875],[13.171465,284.906621],[11.957969,283.077344],[11.547676,281.413770],[11.688750,279.850625],[12.617656,276.764531],[12.730000,273.296875],[10.496250,268.883125],[7.730000,264.296875],[2.520000,252.296875],[-0.930938,246.156094],[-4.747500,240.648125],[-8.530313,234.714531],[-11.880000,227.296875],[-13.862656,219.380312],[-14.976250,211.379375],[-16.294219,203.337188],[-18.890000,195.296875],[-25.145469,183.220625],[-31.733750,171.166875],[-34.577012,165.005469],[-36.812656,158.678125],[-38.210410,152.127656],[-38.540000,145.296875],[-37.854844,140.384375],[-36.366250,134.541875],[-32.400000,124.296875],[-26.122500,114.133125],[-24.510938,109.040469],[-24.870000,102.296875],[-27.060000,94.296875],[-28.790000,82.296875],[-30.831875,75.304375],[-34.092500,66.459375],[-41.030000,51.296875],[-60.260000,25.296875],[-61.932031,21.229062],[-61.973750,17.819375],[-60.260000,10.296875],[-59.280000,2.296875],[-57.553750,-5.903125],[-56.907656,-9.822187],[-56.780000,-14.703125],[-56.876250,-18.770625],[-57.640000,-22.553125],[-59.782813,-24.350469],[-63.645000,-26.484375],[-70.580000,-29.403125],[-84.580000,-28.723125],[-87.447168,-29.114961],[-89.579219,-29.965937],[-92.421250,-32.718125],[-94.672656,-36.325312],[-97.900000,-40.133125],[-101.224531,-42.220937],[-104.861250,-43.275625],[-112.580000,-43.703125],[-120.136250,-43.681875],[-127.580000,-42.483125],[-151.580000,-33.243125],[-169.580000,-34.703125],[-179.666563,-33.916875],[-188.367500,-32.358125],[-195.924688,-31.361875],[-199.349961,-31.491875],[-202.580000,-32.263125],[-207.238594,-34.573906],[-211.221250,-37.586875],[-218.580000,-44.613125],[-227.745000,-52.869375],[-232.417500,-57.464844],[-235.860000,-61.703125],[-237.339688,-64.750937],[-238.150000,-67.650625],[-238.967813,-70.576562],[-240.470000,-73.703125],[-244.952656,-79.565469],[-250.688750,-86.101875],[-256.145469,-92.688906],[-259.790000,-98.703125],[-260.427031,-101.462344],[-260.371250,-103.946875],[-259.790000,-108.703125],[-260.481250,-112.615625],[-261.420000,-115.703125],[-261.367813,-118.479375],[-260.560000,-121.278125],[-258.260000,-126.703125],[-254.808750,-136.496875],[-252.580000,-146.703125],[-250.880000,-163.703125],[-252.245000,-170.073125],[-252.545000,-173.746563],[-251.600000,-177.703125],[-242.200000,-192.703125],[-235.110000,-200.703125],[-229.800000,-208.613125],[-217.280000,-222.003125],[-212.583750,-224.265625],[-207.580000,-225.823125],[-202.220000,-228.750625],[-197.580000,-232.743125],[-193.802637,-236.811113],[-191.282344,-240.379531],[-188.613750,-246.539375],[-186.775781,-252.266094],[-185.293770,-255.293105],[-182.970000,-258.603125],[-179.770781,-261.589844],[-175.706250,-264.361875],[-167.580000,-269.483125],[-155.580000,-280.703125],[-153.230000,-278.868125],[-150.580000,-277.423125]]);
  }
}

module oshwlogo800px(h=3)
{
  scale([25.4/90, -25.4/90, 1]) union()
  {
    linear_extrude(height=h)
      polygon([[-16.500000,-266.590625],[31.500000,-266.590625],[35.913750,-266.534375],[38.183906,-266.198281],[40.020000,-265.420625],[41.923281,-262.160625],[43.351250,-256.703125],[45.100000,-246.590625],[52.700000,-205.590625],[56.200000,-188.630625],[58.567813,-185.469375],[61.927500,-183.260625],[69.500000,-180.170625],[109.500000,-163.940625],[111.590645,-163.768535],[113.705781,-164.161406],[117.908750,-166.156875],[125.500000,-171.590625],[163.500000,-197.590625],[172.651250,-204.133125],[177.878906,-206.627187],[180.314082,-207.006445],[182.500000,-206.550625],[185.527031,-204.348437],[189.556250,-200.603125],[196.500000,-193.590625],[226.500000,-163.590625],[233.782500,-156.415625],[236.459063,-152.104375],[236.948320,-149.859687],[236.640000,-147.590625],[232.182500,-140.150625],[226.840000,-132.590625],[204.170000,-99.590625],[198.735000,-91.575625],[195.943438,-86.959688],[194.530000,-83.590625],[194.728750,-80.508125],[195.790000,-77.590625],[211.220000,-41.590625],[214.612500,-33.441875],[216.859063,-29.472969],[219.610000,-26.680625],[222.902969,-25.382031],[227.661250,-24.241875],[236.500000,-22.590625],[276.500000,-15.190625],[286.612500,-13.441875],[292.070000,-12.013906],[295.330000,-10.110625],[296.107656,-8.274531],[296.443750,-6.004375],[296.500000,-1.590625],[296.500000,61.409375],[296.451250,65.389375],[295.480000,69.129375],[294.216465,70.392695],[292.297969,71.428438],[287.243750,72.941875],[277.500000,74.609375],[241.500000,81.329375],[231.588750,83.055625],[222.540000,85.389375],[219.320156,88.367812],[216.851250,92.544375],[213.300000,101.409375],[196.980000,142.409375],[196.633398,144.880859],[196.950313,147.303125],[199.030000,151.971875],[205.160000,160.409375],[229.160000,195.409375],[234.117500,202.710625],[236.329062,206.919531],[237.050000,210.409375],[235.319687,214.041250],[231.757500,218.276875],[224.500000,225.409375],[196.500000,253.409375],[189.608750,260.354375],[185.617031,264.009687],[182.500000,266.189375],[180.431699,266.602383],[178.116719,266.266563],[173.136250,264.024375],[164.500000,257.989375],[130.500000,234.549375],[123.356250,229.544375],[119.259844,227.577187],[115.500000,227.209375],[96.500000,236.989375],[91.782500,239.339375],[89.162188,240.012813],[86.720000,239.769375],[84.989063,238.543438],[83.657500,236.621875],[81.780000,232.409375],[72.700000,210.409375],[42.900000,138.409375],[35.080000,119.409375],[33.190000,114.981875],[32.260000,110.419375],[32.972891,108.478281],[34.582500,106.401250],[39.522500,102.131875],[49.500000,95.179375],[57.860156,87.966563],[64.533750,80.444375],[70.125469,72.097188],[75.240000,62.409375],[77.913306,56.103069],[79.938008,49.652520],[81.332534,43.096531],[82.115312,36.473906],[81.919336,23.183965],[79.497500,10.093125],[74.997227,-2.488184],[68.565938,-14.249531],[60.351055,-24.880488],[50.500000,-34.070625],[44.132363,-38.671934],[37.722656,-42.482344],[31.219434,-45.552832],[24.571250,-47.934375],[17.726660,-49.677949],[10.634219,-50.834531],[-4.500000,-51.590625],[-12.808906,-50.868750],[-20.983750,-49.033125],[-28.916719,-46.286250],[-36.500000,-42.830625],[-43.849888,-38.623169],[-50.622070,-33.779414],[-56.794077,-28.357280],[-62.343437,-22.414687],[-67.247681,-16.009556],[-71.484336,-9.199805],[-75.030933,-2.043354],[-77.865000,5.401875],[-79.964067,13.077964],[-81.305664,20.926992],[-81.867319,28.891040],[-81.626563,36.912188],[-80.560923,44.932515],[-78.647930,52.894102],[-75.865112,60.739028],[-72.190000,68.409375],[-66.680937,77.253594],[-60.562500,84.788125],[-53.585312,91.540781],[-45.500000,98.039375],[-37.368750,103.516875],[-33.598906,106.893125],[-32.412598,108.660234],[-31.930000,110.449375],[-33.132500,115.478125],[-35.220000,120.409375],[-42.700000,138.409375],[-72.080000,209.409375],[-80.700000,230.409375],[-82.777500,235.313125],[-84.204375,237.720469],[-85.890000,239.369375],[-88.556094,240.028281],[-91.356250,239.390625],[-96.500000,236.719375],[-115.500000,227.149375],[-118.082500,227.133125],[-120.500000,228.069375],[-162.500000,256.739375],[-170.973750,262.574375],[-175.838281,265.477812],[-179.500000,266.789375],[-181.384844,266.498496],[-183.401875,265.566719],[-187.562500,262.415625],[-194.500000,255.409375],[-226.500000,223.409375],[-232.957500,216.975625],[-235.795312,213.122656],[-236.880000,209.409375],[-235.567031,205.754688],[-232.661250,200.879375],[-226.830000,192.409375],[-205.500000,161.409375],[-200.568750,154.221875],[-196.440000,147.409375],[-196.385938,143.771719],[-197.605000,139.390625],[-200.900000,131.409375],[-217.910000,89.449375],[-221.127969,86.020938],[-225.211250,84.229375],[-234.500000,82.609375],[-277.500000,74.609375],[-287.240000,72.863125],[-292.338750,71.331406],[-295.480000,69.129375],[-296.451250,65.389375],[-296.500000,61.409375],[-296.500000,-1.590625],[-296.447500,-5.591875],[-295.480000,-9.360625],[-294.130527,-10.698750],[-292.007969,-11.819375],[-286.333750,-13.505625],[-275.500000,-15.340625],[-233.500000,-23.170625],[-228.029687,-24.003906],[-223.090000,-25.066875],[-218.810313,-27.286719],[-215.320000,-31.590625],[-198.500000,-70.590625],[-195.253750,-77.966875],[-194.330469,-81.892656],[-194.820000,-85.590625],[-206.780000,-103.590625],[-227.360000,-133.590625],[-233.807500,-142.723125],[-236.275625,-148.018750],[-236.677656,-150.451875],[-236.280000,-152.590625],[-232.905156,-157.004062],[-226.726250,-163.508125],[-215.500000,-174.590625],[-191.500000,-198.590625],[-186.401250,-203.671875],[-183.398594,-205.983281],[-180.500000,-207.140625],[-177.010156,-206.419688],[-172.801250,-204.208125],[-165.500000,-199.250625],[-127.500000,-173.170625],[-118.897500,-167.035625],[-113.974688,-164.522188],[-111.640898,-163.903555],[-109.500000,-163.900625],[-92.500000,-170.590625],[-61.520000,-183.410625],[-58.996719,-185.205820],[-57.110000,-187.397812],[-54.785000,-192.665625],[-52.700000,-204.590625],[-44.700000,-247.590625],[-43.212500,-257.161875],[-41.800313,-261.775469],[-39.220000,-265.570625],[-34.366406,-266.527344],[-28.178750,-266.789375],[-16.500000,-266.590625]]);
  }
}

module balloon()
{
    union ()
    {
        // balloon
        scale ([0.8, 1, 1])
        cylinder (h = 4, r=10, center = true, $fn=100);

        // middle knot piece
        knotPiece();

        // left knot piece
        rotate ([0, 0, -6.5])
        knotPiece();

        // right knot piece
        rotate ([0, 0, 6.5])
        knotPiece();
    }
}

module knotPiece()
{
    translate ([0, -10.5, 0])
    scale ([0.3, 0.8, 1])
    cylinder (h = 4, r=2, center = true, $fn=100);
}

module blueMoon()
{
    difference()
    {
        // blue moon
        cylinder (h = 4, r=10, center = true, $fn=100);

        // top cutout
        translate([5, 5, 0])
        cylinder (h = 4.20, r=6, center = true, $fn=100);

        // bottom cutout
        translate([5, -5, 0])
        cylinder (h = 4.20, r=6, center = true, $fn=100);

        // remainder cutout
        translate([10, 0, 5])
        color("red")
        cylinder (h = 14.20, r=6, center = true, $fn=100);
    }
}

module clover(sideHeartRotation = 100)
{
    union ()
    {
        rotate ([0, 0, sideHeartRotation])
        translate ([0,14,0])
        raisedHeart();

        rotate ([0, 0, 0])
        translate ([0,14,0])
        raisedHeart();

        rotate ([0, 0, -sideHeartRotation])
        translate ([0, 14, 0])
        raisedHeart();

//      color ("red")
        translate([-3.5,-30,0])
        cube (size = [7, 40, 15]);
    }
}

module disk(height = 3)
{
    cylinder (h = height, r=10.9, center = true, $fn=100);
}

module heart()
{
    rotate ([0, 0, 45])
    linear_extrude(height=10)
    flatHeart();
}

module hourglass()
{
    union ()
    {
        // top bar
        bar();

        // top glass
        rotate ([0, 0, 180])
        translate ([0, -43, 0])
        color("teal")
        linear_extrude(height=3)
        horseshoeProjection();

        // botton glass
        translate ([0, -43, 0])
        linear_extrude(height=3)
        horseshoeProjection();

        // bottom bar
        translate ([0, -92, 0])
        bar();
    }
}

module bar()
{
    translate ([-30, 43, 0])
    color ("black")
    linear_extrude(height=3)
    square ([60 , 6]);
}

module horseshoe()
{
    linear_extrude(height=3)
    difference()
    {
        horseshoeProjection();

        translate ([0, -1, 0])
        scale ([0.85, .9, 1])
        horseshoeProjection();
    }
}

module horseshoeProjection()
{
    rotate ([0, 0, 90])
    translate ([45, 0, 0])
    projection(cut=true) // the projection is from http://blog.bangsplatpresents.com/?p=1123
    {
        translate( v=[0,0,25] )
        {
            rotate( a=[0,45,0] )
            {
                cylinder( r1=25, r2=0, h=100, center=true );
            }
        }
    }
}

module oval(height = 3,
            xScale = 1.2,
            yScale = 1.4)
{
    scale (v=[xScale, yScale, 1])
    cylinder(h = height, r=20);
}

module crucifixionCcross(height=2)
{
    beamWidth = 3;

    union()
    {
        // vertical beam
        xTranslate = -beamWidth / 2.0;
        yLength = 13;
        color("brown")
        translate([xTranslate, 0, 0])
        cube([3, yLength, height]);

        // horizontal beam
        yTranslate = yLength * 0.5;
        xLength = yLength * 0.75;
        xTranslateHBeam = -xLength / 2.0;

        color("green")
        translate([xTranslateHBeam, yTranslate, 0])
        cube([xLength, 3, height]);
    }
}

module starOfDavid()
{
    height = 3;

    union()
    {
        triangle(height = height);

        rotate([0, 0, 180])
        color("green")
        triangle(height = height);
    }
}

module crescentStar()
{
    height = 3;

    xyScale = 10;
    scale([xyScale, xyScale,1])
    crescentMoon();

    xyTranslate = 25;
    translate([xyTranslate, xyTranslate, 0])
    star();
}

module spurs(h)
{
  scale([25.4/90, -25.4/90, 1]) union()
  {
    linear_extrude(height=h)
      polygon([[13.500000,-56.000000],[29.500000,-55.000000],[54.500000,-55.000000],[58.503750,-55.048750],[60.522969,-55.341719],[62.290000,-56.020000],[64.325156,-57.853594],[66.241250,-60.541250],[69.240000,-66.000000],[80.500000,-87.000000],[106.280000,-135.000000],[118.870000,-159.000000],[122.780000,-198.000000],[124.023594,-204.882813],[125.843750,-209.652500],[128.457031,-214.095937],[132.080000,-220.000000],[148.490000,-248.000000],[153.376719,-256.487656],[155.041895,-259.143652],[156.518750,-260.956250],[158.055137,-262.086816],[159.898906,-262.696719],[165.500000,-263.000000],[214.500000,-263.000000],[214.500000,-213.000000],[213.360000,-196.000000],[213.360000,-154.000000],[213.495000,-150.462500],[213.360000,-147.000000],[196.920000,-117.000000],[156.350000,-45.000000],[125.920000,9.000000],[120.671250,18.592500],[117.385469,23.577187],[115.794199,25.366055],[114.320000,26.400000],[112.797344,26.797500],[110.981250,26.970000],[107.500000,27.000000],[79.500000,27.000000],[65.500000,28.000000],[31.500000,28.000000],[27.943750,28.030000],[24.500000,28.600000],[22.684180,29.597539],[20.548438,31.277812],[15.792500,35.922500],[7.670000,45.000000],[-36.500000,94.040000],[-25.500000,94.040000],[-15.500000,95.000000],[1.500000,95.000000],[22.500000,96.000000],[2.500000,114.080000],[-38.500000,149.000000],[-23.230000,165.000000],[-3.230000,188.000000],[14.500000,210.000000],[-66.500000,189.000000],[-91.500000,263.000000],[-92.970664,261.624141],[-94.426562,259.592500],[-97.197500,254.302500],[-101.500000,244.000000],[-121.500000,198.000000],[-200.500000,222.000000],[-174.840000,182.000000],[-154.500000,151.000000],[-187.500000,128.020000],[-214.500000,108.000000],[-166.500000,103.830000],[-135.500000,101.000000],[-137.410000,77.000000],[-139.590000,41.000000],[-140.500000,31.000000],[-138.108496,32.343340],[-135.722969,34.055469],[-131.038750,38.223750],[-122.500000,47.000000],[-111.500000,57.040000],[-94.500000,74.000000],[-77.500000,27.000000],[-107.500000,26.000000],[-117.196250,25.451250],[-122.812656,24.814531],[-126.090000,23.980000],[-127.513906,22.488438],[-128.773750,20.335000],[-130.730000,16.000000],[-138.200000,-1.000000],[-140.195000,-5.868750],[-140.649688,-8.406719],[-140.330000,-11.000000],[-134.780000,-21.000000],[-120.780000,-45.000000],[-74.650000,-124.000000],[-55.110000,-158.000000],[-46.570000,-206.000000],[-30.280000,-238.000000],[-21.920000,-254.000000],[-19.818750,-257.793750],[-18.535156,-259.646094],[-17.110000,-260.980000],[-15.251406,-261.684844],[-12.943750,-261.983750],[-8.500000,-261.990000],[5.500000,-261.000000],[19.500000,-261.000000],[31.500000,-260.040000],[43.500000,-260.040000],[43.500000,-217.000000],[44.500000,-200.000000],[44.500000,-162.000000],[43.800000,-154.000000],[28.100000,-127.000000],[-14.500000,-56.000000],[13.500000,-56.000000]]);
  }
}

module star(h)
{
  scale([25.4/90, -25.4/90, 1]) union()
  {
    linear_extrude(height=h)
      polygon([[9.080000,-22.000000],[10.922500,-17.093750],[12.213125,-14.728281],[13.890000,-13.020000],[15.773906,-12.298125],[18.041250,-12.022500],[22.500000,-11.910000],[34.390000,-10.968750],[40.862812,-10.133906],[45.500000,-9.000000],[28.500000,4.610000],[21.270000,12.170000],[22.870000,22.000000],[27.500000,43.000000],[8.500000,31.580000],[-0.500000,27.200000],[-10.500000,32.320000],[-28.500000,43.000000],[-22.870000,21.000000],[-21.690000,11.090000],[-28.500000,4.130000],[-45.500000,-11.000000],[-11.500000,-13.000000],[-0.500000,-43.000000],[2.289219,-38.828594],[4.908750,-33.096250],[9.080000,-22.000000]]);
  }
}

module texas(h = 3)
{
  scale([25.4/90, -25.4/90, 1]) union()
  {
    linear_extrude(height=h)
      polygon([[-0.000625,-379.500000],[-0.000625,-252.500000],[0.795937,-245.904219],[3.191875,-241.733750],[7.241562,-238.528906],[12.999375,-234.830000],[23.379375,-227.987500],[29.283750,-224.567187],[33.999375,-222.630000],[42.999375,-222.630000],[48.664219,-221.990156],[54.088125,-220.458750],[59.217656,-218.100469],[63.999375,-214.980000],[71.150625,-208.972500],[74.910469,-206.176875],[78.999375,-204.060000],[106.999375,-198.130000],[113.231875,-196.239375],[117.506875,-194.442500],[124.999375,-191.430000],[143.999375,-189.060000],[160.999375,-184.960000],[165.444414,-184.693203],[170.080938,-185.227500],[179.576875,-187.617500],[188.784063,-189.966250],[193.059648,-190.448984],[196.999375,-190.110000],[200.435176,-188.790957],[203.504531,-186.692031],[209.170625,-181.403750],[212.080723,-178.839004],[215.251094,-176.743594],[218.838418,-175.429824],[222.999375,-175.210000],[227.598437,-176.005234],[232.323125,-177.416875],[241.984375,-181.420000],[251.653125,-185.880625],[260.999375,-189.460000],[267.290313,-190.971719],[272.521875,-191.451250],[283.999375,-190.540000],[292.999375,-190.540000],[300.536875,-189.371406],[307.129375,-187.273750],[313.406875,-184.356719],[319.999375,-180.730000],[326.113438,-177.697500],[332.206875,-175.415000],[344.999375,-171.870000],[352.124375,-169.785000],[355.681250,-168.177188],[358.259375,-166.110000],[359.398906,-163.958750],[359.898125,-161.507500],[359.999375,-156.500000],[359.999375,-118.500000],[360.999375,-101.500000],[361.308125,-79.733750],[362.491406,-68.749844],[365.089375,-58.500000],[369.369531,-50.203281],[375.450625,-41.626250],[382.013594,-32.736094],[387.739375,-23.500000],[392.570625,-12.382500],[394.161719,-6.619375],[395.099375,-0.500000],[395.099375,8.500000],[397.999375,31.500000],[398.000625,41.646250],[397.390469,46.573594],[395.909375,51.500000],[393.784063,55.601406],[391.274375,58.968750],[385.439375,65.500000],[378.478125,74.741250],[372.199375,84.500000],[365.138125,97.467500],[360.990156,104.156562],[356.959375,108.530000],[353.507012,110.351836],[349.562344,111.650312],[340.870625,113.370000],[332.233281,115.074687],[328.356582,116.354414],[324.999375,118.150000],[320.388437,122.233613],[316.306250,127.396406],[308.876875,139.651250],[301.008750,152.297969],[296.378125,157.950605],[290.999375,162.720000],[285.207520,166.355937],[279.138281,169.243750],[266.460625,173.570000],[253.552344,177.288750],[240.999375,181.990000],[235.013594,185.262031],[230.078750,188.835000],[222.251875,196.640000],[215.298750,204.917500],[206.999375,213.180000],[199.696094,218.223906],[192.328125,222.331250],[185.130781,226.942969],[181.669629,229.888262],[178.339375,233.500000],[174.527656,239.822656],[171.883125,246.986250],[169.664219,254.406719],[167.129375,261.500000],[162.033281,270.572656],[156.233125,279.488750],[153.536895,284.407520],[151.226094,289.910469],[149.487871,296.205371],[148.509375,303.500000],[148.726602,309.336465],[149.965938,315.742344],[154.581875,329.431250],[160.499062,342.904531],[165.859375,354.500000],[169.566875,363.312500],[171.068125,368.050625],[171.789375,372.500000],[171.161094,376.538438],[169.058125,378.617500],[165.873281,379.387813],[161.999375,379.500000],[155.657500,379.104219],[149.349375,378.051250],[136.999375,374.780000],[109.568125,365.266250],[95.561406,359.548906],[82.999375,353.750000],[69.848125,346.902500],[63.836406,342.739063],[58.459375,337.490000],[53.696660,330.723262],[49.967656,323.317969],[47.001074,315.435254],[44.525625,307.236250],[39.962969,290.533906],[37.333184,282.352832],[34.109375,274.500000],[12.999375,240.500000],[1.588281,221.689531],[-11.104375,201.698750],[-24.537656,182.358594],[-38.170625,165.500000],[-49.176875,154.292500],[-61.000625,144.000000],[-72.000625,136.180000],[-78.753281,129.575937],[-85.034375,122.347500],[-91.298594,115.505313],[-98.000625,110.060000],[-104.473906,107.202813],[-112.046875,105.487500],[-119.846719,104.668437],[-127.000625,104.500000],[-136.632031,105.592344],[-145.191875,108.626250],[-152.823594,113.597031],[-159.670625,120.500000],[-168.413906,132.824063],[-172.439199,138.787930],[-176.696875,144.212500],[-181.534395,148.792383],[-187.299219,152.222188],[-194.338809,154.196523],[-203.000625,154.410000],[-209.851719,153.008750],[-216.559375,150.302500],[-229.000625,143.300000],[-264.000625,121.350000],[-273.784375,113.561250],[-277.769219,109.072031],[-281.190625,103.500000],[-283.524688,97.963809],[-285.157500,92.341719],[-287.043125,81.103750],[-288.295000,70.313906],[-290.360625,60.500000],[-292.813535,54.220937],[-295.951406,48.236250],[-303.841875,37.090000],[-313.151719,26.941250],[-323.000625,17.670000],[-379.000625,-29.500000],[-385.416094,-36.333750],[-391.279375,-43.985000],[-395.753281,-52.393750],[-397.207598,-56.863438],[-398.000625,-61.500000],[-197.000625,-61.500000],[-197.000625,-379.500000],[-0.000625,-379.500000]]);
  }
}

/**
 * this modeled after a 5mm LED
 */
module throwieCutout(height=2)
{
    ledWidth = 10;
    ledHeight = 13;

    union()
    {
        // LED bottom cutout
        ledBottomCutoutLengthX = ledWidth + 1 + 1;
        xTranslate = -ledBottomCutoutLengthX / 2.0;
        yLength = 13;
        color("brown")
        translate([xTranslate, 0, 0])
        cube([ledBottomCutoutLengthX, 2, height]);

        // LED middle coutout
        yTranslate = 1.5;
        xLength = ledWidth + 1;
        xTranslateHBeam = -xLength / 2.0;
        color("green")
        translate([xTranslateHBeam, yTranslate, 0])
        cube([xLength, 7, height]);

        // LED curved top
        curvedTopTranslateY = (2 + 7);
        curvedTopRadius = (ledWidth / 2.0) + 0.5;
        color("red")
        translate([0, curvedTopTranslateY, 0])
        cylinder (h = height, r=curvedTopRadius, $fn=100);

        // battery
        batteryRadius = 10;
        translate([0, -11, 0])
        cylinder (h = height, r=batteryRadius, $fn=100);
    }
}

module christmasTree(height = 3)
{
    union()
    {
        // top triangle
        translate([0, 30, 0])
        triangle(10, height);

        // middle triangle
        translate([0, 15, 0])
        color("green")
        triangle(15, height);

        // bottom triangle
        triangle(20, height);

        // trunk
        color("brown")
        translate([-2.5, -15, 0])
        cube([5,6, height]);
    }
}

module triangle(size, height)
{
    rotate([0, 0, 90])
    cylinder(r=size,
             $fn=3,
             h=height);
}