Beispiel #1
0
def ZMotorMount(
z_rail_type = 'smooth rod', 
z_rod_diameter = 8, 
z_rod_spacing = 30, 
extrusion_profile = 20, 
extrusion_y_length = 420, 
extrusion_diagonal_length = 340, 
#how far apart should the rod clamp bolt holes be?
hole_spacing = 30, 
thick_typical = 4.25, 
thick_compress = 3
):

    #how big are the structural bolts?
    main_bolt_hole_diameter = 5.5
    nut_depth = 4
    nut_width = 8.5
    #how big are the motor bolts?
    motor_bolt_hole_diameter = 3.5
    motor_bolt_head_diameter = 6 #?

    #lots of math to figure out the horizontal span of the mount based on the extrusions
    #15 is the length added to the diagonal extrusion by the angled plastic part of Lower Vertex Middle
    extrusion_hole_spacing = extrusion_y_length-((15+extrusion_diagonal_length+(extrusion_profile/2))*math.sin(math.radians(30))-(extrusion_profile/2)*math.cos(math.radians(30)))*2
    box = Part.makeBox(extrusion_hole_spacing-(extrusion_profile/2*math.cos(math.radians(30))-extrusion_profile/2*math.sin(math.radians(30)))*2,extrusion_profile*math.cos(math.radians(30))+thick_typical,thick_typical)
    mount = box

    #housings for the upper X extrusions
    box = Part.makeBox(extrusion_profile,extrusion_profile,thick_typical)
    box2= Part.makeBox(thick_typical,extrusion_profile,75)
    box2.translate(Base.Vector(extrusion_profile,0,0))
    box = box.fuse(box2)
    #add mounting on the inner side of the extrusion?
    #box2= Part.makeBox(extrusion_profile+thick_typical,thick_typical,75)
    #box2.translate(Base.Vector(0,-thick_typical,0))
    #box = box.fuse(box2)
    #bolt holes
    cylinder = Part.makeCylinder(main_bolt_hole_diameter/2,thick_typical)
    cylinder.translate(Base.Vector(extrusion_profile/2,extrusion_profile/2,0))
    box = box.cut(cylinder)
    cylinder = Part.makeCylinder(main_bolt_hole_diameter/2,thick_typical)
    cylinder.rotate(Base.Vector(0,0,0),Base.Vector(1,0,0),90)
    cylinder.translate(Base.Vector(extrusion_profile/2,0,75-extrusion_profile/2))
    #bolt holes on the inner side
    #box = box.cut(cylinder)
    #cylinder.translate(Base.Vector(0,0,-20))
    #box = box.cut(cylinder)
    cylinder.rotate(Base.Vector(extrusion_profile+thick_typical/2,-thick_typical/2,0),Base.Vector(0,0,1),-90)
    box = box.cut(cylinder)
    #second bolt hole on the top side
    #cylinder.translate(Base.Vector(0,0,20))
    #box = box.cut(cylinder)
    box.rotate(Base.Vector(0,0,0),Base.Vector(0,0,1),60)
    mount = mount.fuse(box)
    #mirror behaves oddly with rotated parts, so we unrotate before mirroring
    box.rotate(Base.Vector(0,0,0),Base.Vector(0,0,1),-60)
    box = box.mirror(Base.Vector((extrusion_hole_spacing-(extrusion_profile/2*math.cos(math.radians(30))-extrusion_profile/2*math.sin(math.radians(30)))*2)/2,0,0),Base.Vector(1,0,0))
    box.rotate(Base.Vector(extrusion_hole_spacing-(extrusion_profile/2*math.cos(math.radians(30))-extrusion_profile/2*math.sin(math.radians(30)))*2,0,0),Base.Vector(0,0,1),-60)
    mount = mount.fuse(box)

    #TODO: use parametric motor dimensions
    #horizontal motor mount plate
    box = Part.makeBox(extrusion_hole_spacing-(extrusion_profile/2*math.cos(math.radians(30))+extrusion_profile/2*math.sin(math.radians(30)))*2,thick_typical,75)
    box.translate(Base.Vector(extrusion_profile*math.sin(math.radians(30)),extrusion_profile*math.cos(math.radians(30)),0))
    mount = mount.fuse(box)
    #motor hole
    cylinder = Part.makeCylinder(25/2,thick_typical)
    cylinder.rotate(Base.Vector(0,0,0),Base.Vector(1,0,0),-90)
    cylinder.translate(Base.Vector((extrusion_hole_spacing-(extrusion_profile/2*math.cos(math.radians(30))+extrusion_profile/2*math.sin(math.radians(30)))*2)/2,0,z_rod_spacing))
    cylinder.translate(Base.Vector(extrusion_profile*math.sin(math.radians(30)),extrusion_profile*math.cos(math.radians(30)),0))
    mount = mount.cut(cylinder)
    #motor bolt hole
    cylinder = Part.makeCylinder(motor_bolt_hole_diameter/2,thick_typical)
    #conditionally necessary counterbore 
    cylinder2 = Part.makeCylinder(motor_bolt_head_diameter/2,99)
    cylinder2.translate(Base.Vector(0,0,(thick_typical-thick_compress)-99))
    cylinder = cylinder.fuse(cylinder2)
    cylinder.rotate(Base.Vector(0,0,0),Base.Vector(1,0,0),-90)
    cylinder.translate(Base.Vector((extrusion_hole_spacing-(extrusion_profile/2*math.cos(math.radians(30))+extrusion_profile/2*math.sin(math.radians(30)))*2)/2-31/2,0,z_rod_spacing-31/2))
    cylinder.translate(Base.Vector(extrusion_profile*math.sin(math.radians(30)),extrusion_profile*math.cos(math.radians(30)),0))
    mount = mount.cut(cylinder)
    cylinder.translate(Base.Vector(31,0,0))
    mount = mount.cut(cylinder)
    cylinder.translate(Base.Vector(0,0,31))
    mount = mount.cut(cylinder)
    cylinder.translate(Base.Vector(-31,0,0))
    mount = mount.cut(cylinder)

    #move the mount over so we can build the latch in place before moving it back
    mount.translate(Base.Vector(-((extrusion_hole_spacing-(extrusion_profile/2*math.cos(math.radians(30))-extrusion_profile/2*math.sin(math.radians(30)))*2)/2-(7+hole_spacing/2)),0,0))

    #TODO: the common bits from this, RodLatch, and YRodMount should end up in a file together
    #bounding box for the main curved part of the latch
    box = Part.makeBox(hole_spacing,extrusion_profile*math.cos(math.radians(30))+thick_typical,z_rod_diameter/2+thick_typical)
    box.translate(Base.Vector(7,0,0))

    #main curved part of the latch, around the rod
    cylinder = Part.makeCylinder(z_rod_diameter/2+thick_typical,extrusion_profile*math.cos(math.radians(30))+thick_typical)
    cylinder.rotate(Base.Vector(0,0,0),Base.Vector(1,0,0),-90)
    cylinder.translate(Base.Vector(7+hole_spacing/2,0,0))
    latch = box.common(cylinder)

    #connects the curved part to the bolt holes
    box = Part.makeBox(hole_spacing,14,max(thick_typical,thick_compress))
    box.translate(Base.Vector(7,0,0))
    latch = latch.fuse(box)
    mount = mount.fuse(latch)

    #rod hole
    cylinder = Part.makeCylinder(z_rod_diameter/2,extrusion_profile*math.cos(math.radians(30))+thick_typical)
    cylinder.rotate(Base.Vector(0,0,0),Base.Vector(1,0,0),-90)
    cylinder.translate(Base.Vector(7+hole_spacing/2,0,0))
    mount = mount.cut(cylinder)

    #housings for the bolt holes
    cylinder = Part.makeCylinder(7,thick_compress+nut_depth)
    cylinder.translate(Base.Vector(7,7,0))
    mount = mount.fuse(cylinder)
    cylinder = Part.makeCylinder(7,thick_compress+nut_depth)
    cylinder.translate(Base.Vector(7+hole_spacing,7,0))
    mount = mount.fuse(cylinder)

    #bolt holes
    cylinder = Part.makeCylinder(main_bolt_hole_diameter/2,z_rod_diameter/2+thick_typical)
    cylinder.translate(Base.Vector(7,7,0))
    mount = mount.cut(cylinder)
    cylinder = Part.makeCylinder(main_bolt_hole_diameter/2,z_rod_diameter/2+thick_typical)
    cylinder.translate(Base.Vector(7+hole_spacing,7,0))
    mount = mount.cut(cylinder)
    #captive nuts
    nuthole = regPolygon(sides = 6, radius = nut_width/2, extrude = nut_depth, Z_offset = 0)
    nuthole.translate(Base.Vector(7,7,thick_compress))
    mount = mount.cut(nuthole)
    nuthole = regPolygon(sides = 6, radius = nut_width/2, extrude = nut_depth, Z_offset = 0)
    nuthole.translate(Base.Vector(7+hole_spacing,7,thick_compress))
    mount = mount.cut(nuthole)

    #move the mount back into postive coordinates
    mount.translate(Base.Vector(((extrusion_hole_spacing-(extrusion_profile/2*math.cos(math.radians(30))-extrusion_profile/2*math.sin(math.radians(30)))*2)/2-(7+hole_spacing/2)),0,0))
    mount.translate(Base.Vector(extrusion_profile*math.cos(math.radians(30)),0,0))
    
    return mount
Beispiel #2
0
def YRodMount(
extrusion_profile = 20, 
y_rail_type = 'smooth rod', 
y_rod_diameter = 8, 
y_rod_spacing = 100, 
#how far apart should the bottom frame rectangles be?
frame_rectangle_spacing = 30, 
#how thick should the parts be?
thick_typical = 4.25, 
thick_compress = 3, 
thick_min = 1, 
#how far apart should the rod bolt holes be?
hole_spacing = 30
):

    #TODO: fail if y_rail_type is not 'smooth rod'

    #TODO: add logic to specify bolt type instead of bolt dimensions
    #how big are the bolts?
    bolt_hole_diameter = 5.5
    nut_depth = 4
    nut_width = 8.5

    #large printer version raises concerns, so this is an override to always use the 100mm-wide version
    small_printer = True

    #if(small_printer and y_rod_spacing>100):
        #error

    #TODO: make sure tower_y > nut_depth + thick_compress
    tower_x = y_rod_diameter/2+thick_compress
    tower_y = hole_spacing+nut_width+thick_min*2
    tower_z = nut_width*math.sqrt(3)+thick_min*2

    mount_x = y_rod_spacing
    mount_y = frame_rectangle_spacing+extrusion_profile*2
    mount_z = thick_typical

    #base
    box = Part.makeBox(mount_x,mount_y,mount_z)
    box2 = Part.makeBox(mount_x-tower_x*2,frame_rectangle_spacing,mount_z)
    box2.translate(Base.Vector(tower_x,extrusion_profile,0))
    mount = box.cut(box2)

    #"towers"
    box = Part.makeBox(tower_x,tower_y,tower_z)
    box.translate(Base.Vector(0,(mount_y-tower_y)/2,mount_z))
    mount = mount.fuse(box)
    box.translate(Base.Vector(y_rod_spacing-tower_x,0,0))
    mount = mount.fuse(box)

    #rod clamp bolt holes
    nuthole = regPolygon(sides = 6, radius = nut_width/2, extrude = nut_depth, Z_offset = tower_x-nut_depth)
    cylinder = Part.makeCylinder(bolt_hole_diameter/2,tower_x)
    cutout = cylinder.fuse(nuthole)
    cutout.rotate(Base.Vector(0,0,0),Base.Vector(0,1,0),90)
    cutout.translate(Base.Vector(0,mount_y/2-hole_spacing/2,mount_z+tower_z/2))
    mount = mount.cut(cutout)
    #rotations around lines in the middle of the part to re-use the same cutout
    cutout.rotate(Base.Vector(0,mount_y/2,mount_z+tower_z/2),Base.Vector(1,0,0),180)
    mount = mount.cut(cutout)
    cutout.rotate(Base.Vector(mount_x/2,mount_y/2,0),Base.Vector(0,0,1),180)
    mount = mount.cut(cutout)
    cutout.rotate(Base.Vector(0,mount_y/2,mount_z+tower_z/2),Base.Vector(1,0,0),180)
    mount = mount.cut(cutout)

    #extrusion bolt holes and corner rounding
    cornerbox = Part.makeBox(extrusion_profile/2,extrusion_profile/2,mount_z)
    cornercylinder = Part.makeCylinder(extrusion_profile/2,mount_z)
    cornercylinder.translate(Base.Vector(extrusion_profile/2,extrusion_profile/2,0))
    cornerbox=cornerbox.cut(cornercylinder)
    cylinder = Part.makeCylinder(bolt_hole_diameter/2,mount_z)
    #TODO: deal with bolt hole being too close to tower
    if(small_printer):
        cylinder.translate(Base.Vector(extrusion_profile/2,extrusion_profile/2,0))
    else:
        box = Part.makeBox(extrusion_profile,mount_y,mount_z)
        box.translate(Base.Vector(-extrusion_profile,0,0))
        mount=mount.fuse(box)
        box.translate(Base.Vector(mount_x+extrusion_profile,0,0))
        mount=mount.fuse(box)
        cylinder.translate(Base.Vector(-extrusion_profile/2,extrusion_profile/2,0))
        cornerbox.translate(Base.Vector(-extrusion_profile,0,0))
    #add the corner rounding
    cylinder=cylinder.fuse(cornerbox)
    mount = mount.cut(cylinder)
    #rotations around lines in the middle of the part to re-use the same cutout
    cylinder.rotate(Base.Vector(0,mount_y/2,mount_z/2),Base.Vector(1,0,0),180)
    mount = mount.cut(cylinder)
    cylinder.rotate(Base.Vector(mount_x/2,0,mount_z/2),Base.Vector(0,1,0),180)
    mount = mount.cut(cylinder)
    cylinder.rotate(Base.Vector(0,mount_y/2,mount_z/2),Base.Vector(1,0,0),180)
    mount = mount.cut(cylinder)

    #rod holes
    cylinder = Part.makeCylinder(y_rod_diameter/2,tower_z+mount_z)
    cylinder.translate(Base.Vector(0,mount_y/2,0))
    mount = mount.cut(cylinder)
    cylinder.translate(Base.Vector(y_rod_spacing,0,0))
    mount = mount.cut(cylinder)
    
    return mount
Beispiel #3
0
def YRodMount(
        extrusion_profile=20,
        y_rail_type='smooth rod',
        y_rod_diameter=8,
        y_rod_spacing=100,
        #how far apart should the bottom frame rectangles be?
        frame_rectangle_spacing=30,
        #how thick should the parts be?
        thick_typical=4.25,
        thick_compress=3,
        thick_min=1,
        #how far apart should the rod bolt holes be?
        hole_spacing=30):

    #TODO: fail if y_rail_type is not 'smooth rod'

    #TODO: add logic to specify bolt type instead of bolt dimensions
    #how big are the bolts?
    bolt_hole_diameter = 5.5
    nut_depth = 4
    nut_width = 8.5

    #large printer version raises concerns, so this is an override to always use the 100mm-wide version
    small_printer = True

    #if(small_printer and y_rod_spacing>100):
    #error

    #TODO: make sure tower_y > nut_depth + thick_compress
    tower_x = y_rod_diameter / 2 + thick_compress
    tower_y = hole_spacing + nut_width + thick_min * 2
    tower_z = nut_width * math.sqrt(3) + thick_min * 2

    mount_x = y_rod_spacing
    mount_y = frame_rectangle_spacing + extrusion_profile * 2
    mount_z = thick_typical

    #base
    box = Part.makeBox(mount_x, mount_y, mount_z)
    box2 = Part.makeBox(mount_x - tower_x * 2, frame_rectangle_spacing,
                        mount_z)
    box2.translate(Base.Vector(tower_x, extrusion_profile, 0))
    mount = box.cut(box2)

    #"towers"
    box = Part.makeBox(tower_x, tower_y, tower_z)
    box.translate(Base.Vector(0, (mount_y - tower_y) / 2, mount_z))
    mount = mount.fuse(box)
    box.translate(Base.Vector(y_rod_spacing - tower_x, 0, 0))
    mount = mount.fuse(box)

    #rod clamp bolt holes
    nuthole = regPolygon(sides=6,
                         radius=nut_width / 2,
                         extrude=nut_depth,
                         Z_offset=tower_x - nut_depth)
    cylinder = Part.makeCylinder(bolt_hole_diameter / 2, tower_x)
    cutout = cylinder.fuse(nuthole)
    cutout.rotate(Base.Vector(0, 0, 0), Base.Vector(0, 1, 0), 90)
    cutout.translate(
        Base.Vector(0, mount_y / 2 - hole_spacing / 2, mount_z + tower_z / 2))
    mount = mount.cut(cutout)
    #rotations around lines in the middle of the part to re-use the same cutout
    cutout.rotate(Base.Vector(0, mount_y / 2, mount_z + tower_z / 2),
                  Base.Vector(1, 0, 0), 180)
    mount = mount.cut(cutout)
    cutout.rotate(Base.Vector(mount_x / 2, mount_y / 2, 0),
                  Base.Vector(0, 0, 1), 180)
    mount = mount.cut(cutout)
    cutout.rotate(Base.Vector(0, mount_y / 2, mount_z + tower_z / 2),
                  Base.Vector(1, 0, 0), 180)
    mount = mount.cut(cutout)

    #extrusion bolt holes and corner rounding
    cornerbox = Part.makeBox(extrusion_profile / 2, extrusion_profile / 2,
                             mount_z)
    cornercylinder = Part.makeCylinder(extrusion_profile / 2, mount_z)
    cornercylinder.translate(
        Base.Vector(extrusion_profile / 2, extrusion_profile / 2, 0))
    cornerbox = cornerbox.cut(cornercylinder)
    cylinder = Part.makeCylinder(bolt_hole_diameter / 2, mount_z)
    #TODO: deal with bolt hole being too close to tower
    if (small_printer):
        cylinder.translate(
            Base.Vector(extrusion_profile / 2, extrusion_profile / 2, 0))
    else:
        box = Part.makeBox(extrusion_profile, mount_y, mount_z)
        box.translate(Base.Vector(-extrusion_profile, 0, 0))
        mount = mount.fuse(box)
        box.translate(Base.Vector(mount_x + extrusion_profile, 0, 0))
        mount = mount.fuse(box)
        cylinder.translate(
            Base.Vector(-extrusion_profile / 2, extrusion_profile / 2, 0))
        cornerbox.translate(Base.Vector(-extrusion_profile, 0, 0))
    #add the corner rounding
    cylinder = cylinder.fuse(cornerbox)
    mount = mount.cut(cylinder)
    #rotations around lines in the middle of the part to re-use the same cutout
    cylinder.rotate(Base.Vector(0, mount_y / 2, mount_z / 2),
                    Base.Vector(1, 0, 0), 180)
    mount = mount.cut(cylinder)
    cylinder.rotate(Base.Vector(mount_x / 2, 0, mount_z / 2),
                    Base.Vector(0, 1, 0), 180)
    mount = mount.cut(cylinder)
    cylinder.rotate(Base.Vector(0, mount_y / 2, mount_z / 2),
                    Base.Vector(1, 0, 0), 180)
    mount = mount.cut(cylinder)

    #rod holes
    cylinder = Part.makeCylinder(y_rod_diameter / 2, tower_z + mount_z)
    cylinder.translate(Base.Vector(0, mount_y / 2, 0))
    mount = mount.cut(cylinder)
    cylinder.translate(Base.Vector(y_rod_spacing, 0, 0))
    mount = mount.cut(cylinder)

    return mount
Beispiel #4
0
nut_top = Part.makeBox(nut_length, extrusion_slot_opening_width - gap_horizontal*2, extrusion_slot_opening_depth - gap_vertical)

nut_bottom_width = extrusion_slot_width - gap_horizontal*2
nut_bottom_height = extrusion_slot_depth - gap_vertical
nut_bottom_cross_section = Part.makePolygon([
Base.Vector(0,0,0),
Base.Vector(0,nut_bottom_width,0),
Base.Vector(0,nut_bottom_width,-(extrusion_slot_vertical_depth-gap_vertical)),
Base.Vector(0,nut_bottom_width - (nut_bottom_height-(extrusion_slot_vertical_depth-gap_vertical)),-nut_bottom_height),
Base.Vector(0,nut_bottom_height-(extrusion_slot_vertical_depth-gap_vertical),-nut_bottom_height),
Base.Vector(0,0,-(extrusion_slot_vertical_depth-gap_vertical)),
Base.Vector(0,0,0)])
face = Part.Face(nut_bottom_cross_section)
nut_bottom = face.extrude(Base.Vector(nut_length,0,0))
nut_bottom.translate(Base.Vector(0,-(nut_bottom_width-(extrusion_slot_opening_width - 0.5))/2,0))
nut = nut_bottom.fuse(nut_top)

bolthole = Part.makeCylinder(bolt_diameter/2,extrusion_slot_opening_depth - gap_vertical)
nuthole = regPolygon(sides = 6, radius = metal_nut_width/2, extrude = nut_bottom_height, Z_offset = -nut_bottom_height)
holes = bolthole.fuse(nuthole)
holes.translate(Base.Vector(base_padding,(extrusion_slot_opening_width-gap_horizontal*2)/2,0))
for n in range(num_holes):
    nut = nut.cut(holes)
    holes.translate(Base.Vector(hole_spacing_medium,0,0))

#bring back into octant 1
nut.translate(Base.Vector(0,(nut_bottom_width - (extrusion_slot_opening_width - gap_horizontal*2))/2,nut_bottom_height))

Part.show(nut)
Beispiel #5
0
else:
    box2 = Part.makeBox(y_rod_spacing - y_rod_diameter - part_thickness * 2, 40, part_thickness)
    box2.translate(Base.Vector(y_rod_diameter / 2 + part_thickness, 15, 0))
mount = box.cut(box2)

# "towers"
#
box = Part.makeBox(y_rod_diameter / 2 + part_thickness, 40, nut_width + part_thickness * 2)
box.translate(Base.Vector(0, 15, part_thickness))
mount = mount.fuse(box)
box.translate(Base.Vector(y_rod_spacing - y_rod_diameter / 2 - part_thickness, 0, 0))
mount = mount.fuse(box)

# rod clamp bolt holes
nuthole = regPolygon(
    sides=6, radius=nut_width / 2, extrude=nut_depth, Z_offset=y_rod_diameter / 2 + part_thickness - nut_depth
)
cylinder = Part.makeCylinder(bolt_hole_diameter / 2, y_rod_diameter / 2 + part_thickness)
cutout = cylinder.fuse(nuthole)
cutout.rotate(Base.Vector(0, 0, 0), Base.Vector(0, 1, 0), 90)
cutout.translate(
    Base.Vector(0, 70 / 2 - y_rod_diameter / 2 - (40 - y_rod_diameter) / 4, part_thickness * 2 + nut_width / 2)
)
mount = mount.cut(cutout)
# rotations around lines in the middle of the part to re-use the same cutout
cutout.rotate(
    Base.Vector((y_rod_diameter / 2 + part_thickness) / 2, 70 / 2, part_thickness * 2 + nut_width / 2),
    Base.Vector(1, 0, 0),
    180,
)
mount = mount.cut(cutout)
Beispiel #6
0
        -nut_bottom_height),
    Base.Vector(0, 0, -(extrusion_slot_vertical_depth - gap_vertical)),
    Base.Vector(0, 0, 0)
])
face = Part.Face(nut_bottom_cross_section)
nut_bottom = face.extrude(Base.Vector(nut_length, 0, 0))
nut_bottom.translate(
    Base.Vector(0,
                -(nut_bottom_width - (extrusion_slot_opening_width - 0.5)) / 2,
                0))
nut = nut_bottom.fuse(nut_top)

bolthole = Part.makeCylinder(bolt_diameter / 2,
                             extrusion_slot_opening_depth - gap_vertical)
nuthole = regPolygon(sides=6,
                     radius=metal_nut_width / 2,
                     extrude=nut_bottom_height,
                     Z_offset=-nut_bottom_height)
holes = bolthole.fuse(nuthole)
holes.translate(
    Base.Vector(base_padding,
                (extrusion_slot_opening_width - gap_horizontal * 2) / 2, 0))
for n in range(num_holes):
    nut = nut.cut(holes)
    holes.translate(Base.Vector(hole_spacing_medium, 0, 0))

#bring back into octant 1
nut.translate(
    Base.Vector(0, (nut_bottom_width -
                    (extrusion_slot_opening_width - gap_horizontal * 2)) / 2,
                nut_bottom_height))
Beispiel #7
0
def ZMotorMount(
        z_rail_type='smooth rod',
        z_rod_diameter=8,
        z_rod_spacing=30,
        extrusion_profile=20,
        extrusion_y_length=420,
        extrusion_diagonal_length=340,
        #how far apart should the rod clamp bolt holes be?
        hole_spacing=30,
        thick_typical=4.25,
        thick_compress=3):

    #how big are the structural bolts?
    main_bolt_hole_diameter = 5.5
    nut_depth = 4
    nut_width = 8.5
    #how big are the motor bolts?
    motor_bolt_hole_diameter = 3.5
    motor_bolt_head_diameter = 6  #?

    #lots of math to figure out the horizontal span of the mount based on the extrusions
    #15 is the length added to the diagonal extrusion by the angled plastic part of Lower Vertex Middle
    extrusion_hole_spacing = extrusion_y_length - (
        (15 + extrusion_diagonal_length +
         (extrusion_profile / 2)) * math.sin(math.radians(30)) -
        (extrusion_profile / 2) * math.cos(math.radians(30))) * 2
    box = Part.makeBox(
        extrusion_hole_spacing -
        (extrusion_profile / 2 * math.cos(math.radians(30)) -
         extrusion_profile / 2 * math.sin(math.radians(30))) * 2,
        extrusion_profile * math.cos(math.radians(30)) + thick_typical,
        thick_typical)
    mount = box

    #housings for the upper X extrusions
    box = Part.makeBox(extrusion_profile, extrusion_profile, thick_typical)
    box2 = Part.makeBox(thick_typical, extrusion_profile, 75)
    box2.translate(Base.Vector(extrusion_profile, 0, 0))
    box = box.fuse(box2)
    #add mounting on the inner side of the extrusion?
    #box2= Part.makeBox(extrusion_profile+thick_typical,thick_typical,75)
    #box2.translate(Base.Vector(0,-thick_typical,0))
    #box = box.fuse(box2)
    #bolt holes
    cylinder = Part.makeCylinder(main_bolt_hole_diameter / 2, thick_typical)
    cylinder.translate(
        Base.Vector(extrusion_profile / 2, extrusion_profile / 2, 0))
    box = box.cut(cylinder)
    cylinder = Part.makeCylinder(main_bolt_hole_diameter / 2, thick_typical)
    cylinder.rotate(Base.Vector(0, 0, 0), Base.Vector(1, 0, 0), 90)
    cylinder.translate(
        Base.Vector(extrusion_profile / 2, 0, 75 - extrusion_profile / 2))
    #bolt holes on the inner side
    #box = box.cut(cylinder)
    #cylinder.translate(Base.Vector(0,0,-20))
    #box = box.cut(cylinder)
    cylinder.rotate(
        Base.Vector(extrusion_profile + thick_typical / 2, -thick_typical / 2,
                    0), Base.Vector(0, 0, 1), -90)
    box = box.cut(cylinder)
    #second bolt hole on the top side
    #cylinder.translate(Base.Vector(0,0,20))
    #box = box.cut(cylinder)
    box.rotate(Base.Vector(0, 0, 0), Base.Vector(0, 0, 1), 60)
    mount = mount.fuse(box)
    #mirror behaves oddly with rotated parts, so we unrotate before mirroring
    box.rotate(Base.Vector(0, 0, 0), Base.Vector(0, 0, 1), -60)
    box = box.mirror(
        Base.Vector(
            (extrusion_hole_spacing -
             (extrusion_profile / 2 * math.cos(math.radians(30)) -
              extrusion_profile / 2 * math.sin(math.radians(30))) * 2) / 2, 0,
            0), Base.Vector(1, 0, 0))
    box.rotate(
        Base.Vector(
            extrusion_hole_spacing -
            (extrusion_profile / 2 * math.cos(math.radians(30)) -
             extrusion_profile / 2 * math.sin(math.radians(30))) * 2, 0, 0),
        Base.Vector(0, 0, 1), -60)
    mount = mount.fuse(box)

    #TODO: use parametric motor dimensions
    #horizontal motor mount plate
    box = Part.makeBox(
        extrusion_hole_spacing -
        (extrusion_profile / 2 * math.cos(math.radians(30)) +
         extrusion_profile / 2 * math.sin(math.radians(30))) * 2,
        thick_typical, 75)
    box.translate(
        Base.Vector(extrusion_profile * math.sin(math.radians(30)),
                    extrusion_profile * math.cos(math.radians(30)), 0))
    mount = mount.fuse(box)
    #motor hole
    cylinder = Part.makeCylinder(25 / 2, thick_typical)
    cylinder.rotate(Base.Vector(0, 0, 0), Base.Vector(1, 0, 0), -90)
    cylinder.translate(
        Base.Vector(
            (extrusion_hole_spacing -
             (extrusion_profile / 2 * math.cos(math.radians(30)) +
              extrusion_profile / 2 * math.sin(math.radians(30))) * 2) / 2, 0,
            z_rod_spacing))
    cylinder.translate(
        Base.Vector(extrusion_profile * math.sin(math.radians(30)),
                    extrusion_profile * math.cos(math.radians(30)), 0))
    mount = mount.cut(cylinder)
    #motor bolt hole
    cylinder = Part.makeCylinder(motor_bolt_hole_diameter / 2, thick_typical)
    #conditionally necessary counterbore
    cylinder2 = Part.makeCylinder(motor_bolt_head_diameter / 2, 99)
    cylinder2.translate(
        Base.Vector(0, 0, (thick_typical - thick_compress) - 99))
    cylinder = cylinder.fuse(cylinder2)
    cylinder.rotate(Base.Vector(0, 0, 0), Base.Vector(1, 0, 0), -90)
    cylinder.translate(
        Base.Vector(
            (extrusion_hole_spacing -
             (extrusion_profile / 2 * math.cos(math.radians(30)) +
              extrusion_profile / 2 * math.sin(math.radians(30))) * 2) / 2 -
            31 / 2, 0, z_rod_spacing - 31 / 2))
    cylinder.translate(
        Base.Vector(extrusion_profile * math.sin(math.radians(30)),
                    extrusion_profile * math.cos(math.radians(30)), 0))
    mount = mount.cut(cylinder)
    cylinder.translate(Base.Vector(31, 0, 0))
    mount = mount.cut(cylinder)
    cylinder.translate(Base.Vector(0, 0, 31))
    mount = mount.cut(cylinder)
    cylinder.translate(Base.Vector(-31, 0, 0))
    mount = mount.cut(cylinder)

    #move the mount over so we can build the latch in place before moving it back
    mount.translate(
        Base.Vector(
            -((extrusion_hole_spacing -
               (extrusion_profile / 2 * math.cos(math.radians(30)) -
                extrusion_profile / 2 * math.sin(math.radians(30))) * 2) / 2 -
              (7 + hole_spacing / 2)), 0, 0))

    #TODO: the common bits from this, RodLatch, and YRodMount should end up in a file together
    #bounding box for the main curved part of the latch
    box = Part.makeBox(
        hole_spacing,
        extrusion_profile * math.cos(math.radians(30)) + thick_typical,
        z_rod_diameter / 2 + thick_typical)
    box.translate(Base.Vector(7, 0, 0))

    #main curved part of the latch, around the rod
    cylinder = Part.makeCylinder(
        z_rod_diameter / 2 + thick_typical,
        extrusion_profile * math.cos(math.radians(30)) + thick_typical)
    cylinder.rotate(Base.Vector(0, 0, 0), Base.Vector(1, 0, 0), -90)
    cylinder.translate(Base.Vector(7 + hole_spacing / 2, 0, 0))
    latch = box.common(cylinder)

    #connects the curved part to the bolt holes
    box = Part.makeBox(hole_spacing, 14, max(thick_typical, thick_compress))
    box.translate(Base.Vector(7, 0, 0))
    latch = latch.fuse(box)
    mount = mount.fuse(latch)

    #rod hole
    cylinder = Part.makeCylinder(
        z_rod_diameter / 2,
        extrusion_profile * math.cos(math.radians(30)) + thick_typical)
    cylinder.rotate(Base.Vector(0, 0, 0), Base.Vector(1, 0, 0), -90)
    cylinder.translate(Base.Vector(7 + hole_spacing / 2, 0, 0))
    mount = mount.cut(cylinder)

    #housings for the bolt holes
    cylinder = Part.makeCylinder(7, thick_compress + nut_depth)
    cylinder.translate(Base.Vector(7, 7, 0))
    mount = mount.fuse(cylinder)
    cylinder = Part.makeCylinder(7, thick_compress + nut_depth)
    cylinder.translate(Base.Vector(7 + hole_spacing, 7, 0))
    mount = mount.fuse(cylinder)

    #bolt holes
    cylinder = Part.makeCylinder(main_bolt_hole_diameter / 2,
                                 z_rod_diameter / 2 + thick_typical)
    cylinder.translate(Base.Vector(7, 7, 0))
    mount = mount.cut(cylinder)
    cylinder = Part.makeCylinder(main_bolt_hole_diameter / 2,
                                 z_rod_diameter / 2 + thick_typical)
    cylinder.translate(Base.Vector(7 + hole_spacing, 7, 0))
    mount = mount.cut(cylinder)
    #captive nuts
    nuthole = regPolygon(sides=6,
                         radius=nut_width / 2,
                         extrude=nut_depth,
                         Z_offset=0)
    nuthole.translate(Base.Vector(7, 7, thick_compress))
    mount = mount.cut(nuthole)
    nuthole = regPolygon(sides=6,
                         radius=nut_width / 2,
                         extrude=nut_depth,
                         Z_offset=0)
    nuthole.translate(Base.Vector(7 + hole_spacing, 7, thick_compress))
    mount = mount.cut(nuthole)

    #move the mount back into postive coordinates
    mount.translate(
        Base.Vector(
            ((extrusion_hole_spacing -
              (extrusion_profile / 2 * math.cos(math.radians(30)) -
               extrusion_profile / 2 * math.sin(math.radians(30))) * 2) / 2 -
             (7 + hole_spacing / 2)), 0, 0))
    mount.translate(
        Base.Vector(extrusion_profile * math.cos(math.radians(30)), 0, 0))

    return mount