// Generated by SolidPython 1.0.5 on 2021-06-01 16:28:59
$fn = 120;


difference(){
	union() {
		difference() {
			cylinder(center = true, h = 30, r = 12);
			cylinder(center = true, h = 32, r = 10);
		}
		rotate(a = 90, v = [0, 1, 0]) {
			difference() {
				cylinder(center = true, h = 30, r = 12);
				cylinder(center = true, h = 32, r = 10);
			}
		}
		translate(v = [45, 0, 0]) {
			union() {
				cylinder(center = true, h = 30, r = 12);
				rotate(a = 90, v = [0, 1, 0]) {
					union() {
						cylinder(center = true, h = 30, r = 12);
					}
				}
			}
		}
		translate(v = [0, 0, 40]) {
			union() {
				difference() {
					cube(center = true, size = 10);
				}
				union() {
					cylinder(center = true, h = 14, r = 1.5000000000);
					translate(v = [0, 0, 8]) {
						cylinder(center = true, h = 2.5000000000, r = 2.5000000000);
					}
				}
				translate(v = [45, 0, 0]) {
					union() {
						difference(){
							difference() {
								cube(center = true, size = 10);
							}
							/* Holes Below*/
							union(){
								cylinder(center = true, h = 12, r = 2);
							} /* End Holes */ 
						}
						union() {
							cylinder(center = true, h = 14, r = 1.5000000000);
							translate(v = [0, 0, 8]) {
								cylinder(center = true, h = 2.5000000000, r = 2.5000000000);
							}
						}
					}
				}
			}
		}
	}
	/* Holes Below*/
	union(){
		translate(v = [45, 0, 0]){
			union(){
				cylinder(center = true, h = 32, r = 10);
				rotate(a = 90, v = [0, 1, 0]){
					union(){
						cylinder(center = true, h = 32, r = 10);
					}
				}
			}
		}
		translate(v = [0, 0, 40]){
			union(){
				union(){
					cylinder(center = true, h = 12, r = 2);
				}
			}
		}
	} /* End Holes */ 
}
/***********************************************
*********      SolidPython code:      **********
************************************************
 
#! /usr/bin/env python3
import sys

from solid import scad_render_to_file
from solid.objects import cube, cylinder, hole, part, rotate
from solid.utils import FORWARD_VEC, right, up

SEGMENTS = 120


def pipe_intersection_hole():
    pipe_od = 12
    pipe_id = 10
    seg_length = 30

    outer = cylinder(r=pipe_od, h=seg_length, center=True)
    inner = cylinder(r=pipe_id, h=seg_length + 2, center=True)

    # By declaring that the internal void of pipe_a should
    # explicitly remain empty, the combination of both pipes
    # is empty all the way through.

    # Any OpenSCAD / SolidPython object can be declared a hole(),
    # and after that will always be empty
    pipe_a = outer + hole()(inner)
    # Note that "pipe_a = outer - hole()(inner)" would work identically;
    # inner will always be subtracted now that it's a hole

    pipe_b = rotate(a=90, v=FORWARD_VEC)(pipe_a)
    return pipe_a + pipe_b


def pipe_intersection_no_hole():
    pipe_od = 12
    pipe_id = 10
    seg_length = 30

    outer = cylinder(r=pipe_od, h=seg_length, center=True)
    inner = cylinder(r=pipe_id, h=seg_length + 2, center=True)
    pipe_a = outer - inner

    pipe_b = rotate(a=90, v=FORWARD_VEC)(pipe_a)
    # pipe_a and pipe_b are both hollow, but because
    # their central voids aren't explicitly holes,
    # the union of both pipes has unwanted internal walls

    return pipe_a + pipe_b


def multipart_hole():
    # It's good to be able to keep holes empty, but often we want to put
    # things (bolts, etc.) in them.  The way to do this is to declare the
    # object containing the hole a "part".  Then, the hole will remain
    # empty no matter what you add to the 'part'.  But if you put an object
    # that is NOT part of the 'part' into the hole, it will still appear.

    # On the left (not_part), here's what happens if we try to put an object
    # into an explicit hole:  the object gets erased by the hole.

    # On the right (is_part), we mark the cube-with-hole as a "part",
    # and then insert the same 'bolt' cylinder into it.  The entire
    # bolt rematins.

    b = cube(10, center=True)
    c = cylinder(r=2, h=12, center=True)

    # A cube with an explicit hole
    not_part = b - hole()(c)

    # Mark this cube-with-hole as a separate part from the cylinder
    is_part = part()(not_part.copy())

    # This fits in the holes
    bolt = cylinder(r=1.5, h=14, center=True) + up(8)(cylinder(r=2.5, h=2.5, center=True))

    # The section of the bolt inside not_part disappears.  The section
    # of the bolt inside is_part is still there.
    return not_part + bolt + right(45)(is_part + bolt)


if __name__ == '__main__':
    out_dir = sys.argv[1] if len(sys.argv) > 1 else None

    # On the left, pipes with no explicit holes, which can give
    # unexpected walls where we don't want them.
    # On the right, we use the hole() function to fix the problem
    a = pipe_intersection_no_hole() + right(45)(pipe_intersection_hole())

    # Below is an example of how to put objects into holes and have them
    # still appear
    b = up(40)(multipart_hole())
    a += b

    file_out = scad_render_to_file(a, out_dir=out_dir, file_header=f'$fn = {SEGMENTS};', include_orig_code=True)
    print(f"{__file__}: SCAD file written to: \n{file_out}")
 
 
************************************************/
