import cadquery as cq if __name__ == "__main__": from ocp_vscode import * from utils import * import localselectors tube_w = inch(2.0) tube_h = inch(1.5) tube_wall = inch(0.075) # 1.519 #inch(0.062) column_spacing = 560 column_h = 400 plate_z = inch(3 / 16) # 2.54 plate_z2 = inch(3 / 8) # 10 x_mount_z = inch(3 / 16) # 5 stepper_mount_z = inch(3 / 16) # 5 carrier_plate_z = inch(3 / 8) # 10 ballscrew_x_offset = 4 ballscrew_len = 500 column_spacing = ( ballscrew_len - 15 - 39 + 25 - 10 + 7 / 2 + 20 / 2 + 2 * x_mount_z + tube_w ) print("column_spacing = ", column_spacing) x_rail_spacing = 240 x_carriage_spacing = 120 class Gantry: def __init__(self, w): self.left = tubing( column_h, tube_w, tube_h, tube_wall, w.transformed(offset=(-0.5 * column_spacing, 0, 0)), ) self.right = tubing( column_h, tube_w, tube_h, tube_wall, w.transformed(offset=(0.5 * column_spacing, 0, 0)), ) upper_center = column_h - 0.5 * tube_w self.upper = tubing( column_spacing - tube_w, tube_h, tube_w, tube_wall, w.transformed( offset=(-0.5 * column_spacing + 0.5 * tube_w, 0, upper_center), rotate=(90, 90, 0), ), ) lower_center = upper_center - x_rail_spacing self.lower = tubing( column_spacing - tube_w, tube_h, tube_w, tube_wall, w.transformed( offset=(-0.5 * column_spacing + 0.5 * tube_w, 0, lower_center), rotate=(90, 90, 0), ), ) self.upper_rail = HGR20( w.transformed( offset=(0, 0.5 * tube_h + plate_z, upper_center), rotate=(-90, 0, 0) ), column_spacing + tube_w, ) self.lower_rail = HGR20( w.transformed( offset=(0, 0.5 * tube_h + plate_z, lower_center), rotate=(-90, 0, 0) ), column_spacing + tube_w, ) self.upper_front_plate = ( cq.Workplane() .copyWorkplane( w.transformed(offset=(0, tube_h / 2, upper_center), rotate=(-90, 0, 0)) ) .tag("base") .rect(column_spacing + tube_w, tube_w) .extrude(plate_z) ) self.lower_front_plate = ( cq.Workplane() .copyWorkplane( w.transformed(offset=(0, tube_h / 2, lower_center), rotate=(-90, 0, 0)) ) .tag("base") .rect(column_spacing + tube_w, tube_w) .extrude(plate_z) ) self.upper_back_plate = ( cq.Workplane() .copyWorkplane( w.transformed(offset=(0, -tube_h / 2, upper_center), rotate=(90, 0, 0)) ) .tag("base") .rect(column_spacing + tube_w, tube_w) .extrude(plate_z) ) self.lower_back_plate = ( cq.Workplane() .copyWorkplane( w.transformed(offset=(0, -tube_h / 2, lower_center), rotate=(90, 0, 0)) ) .tag("base") .rect(column_spacing + tube_w, tube_w) .extrude(plate_z) ) self.ball_screw_w = ( cq.Workplane() .copyWorkplane(w) .transformed( offset=( ballscrew_len / 2 - (-15 - 39 + 25 + 10 - 7 / 2 - 20 / 2) / 2, ballscrew_x_offset, (upper_center + lower_center) / 2, ), rotate=(0, 0, 90), ) .transformed(rotate=(0, 90, 0)) ) self.ball_screw_model = SFU1204(self.ball_screw_w, ballscrew_len) self.floating_mount_w = self.ball_screw_w.transformed( offset=(0, ballscrew_len + (-10 + 7 / 2 + 20 / 2), 0), rotate=(-90, 0, 0) ) self.ball_screw = self.ball_screw_model.ballscrew() self.fixed_bearing = self.ball_screw_model.fixedBearing() self.floating_bearing = self.ball_screw_model.floatingBearing() self.left = self.ball_screw_model.floatingBearingHoles(self.left) self.right = self.ball_screw_model.fixedBearingHoles(self.right) self.right = ( self.right # holes for the ball screw .copyWorkplane(self.ball_screw_w.transformed(rotate=(90, 0, 0))) .hole(20) .copyWorkplane(self.ball_screw_w.transformed(rotate=(-90, 0, 0))) .hole(20) ) self.upper_front_plate = self.upper_rail.holes(self.upper_front_plate) self.upper_back_plate = self.upper_rail.holes(self.upper_back_plate) self.lower_front_plate = self.lower_rail.holes(self.lower_front_plate) self.lower_back_plate = self.lower_rail.holes(self.lower_back_plate) right_bearing_base = ( self.ball_screw_w.transformed(offset=(0, 0, -ballscrew_x_offset)) .transformed(rotate=(-90, 0, 0)) .transformed(offset=(0, 0, 15 + 39 - 25 - x_mount_z)) .transformed(rotate=(0, 0, 90)) ) self.right_bearing_mount = ( cq.Workplane() .copyWorkplane(right_bearing_base) .tag("base") .rect(tube_h, x_rail_spacing - tube_w) .extrude(x_mount_z) .center(-ballscrew_x_offset, 0) .tag("ballscrew_center") .circle(12 / 2) .extrude(20, combine="s") .workplaneFromTagged("ballscrew_center") .center(35 / 2 - 4 / 2, 0) .rect(4, 35) .extrude(20, combine="s") .workplaneFromTagged("ballscrew_center") .center(-35 / 2 + 4 / 2, 0) .rect(4, 35) .extrude(20, combine="s") .workplaneFromTagged("ballscrew_center") .center(0, -35 / 2 + 4 / 2) .rect(20, 4) .extrude(20, combine="s") .workplaneFromTagged("ballscrew_center") .center(0, 35 / 2 - 4 / 2) .rect(20, 4) .extrude(20, combine="s") # .rect(35, 35) # .extrude(20, combine="s") ) self.right_bearing_mount = self.ball_screw_model.fixedBearingHoles( self.right_bearing_mount ) self.left_bearing_mount = ( w.copyWorkplane(self.floating_mount_w) .tag("base") .transformed(offset=(0, ballscrew_x_offset, 0), rotate=(0, 0, 90)) .rect(tube_h, x_rail_spacing - tube_w) .extrude(x_mount_z) ) # this doesn't work for some reason, i guess just use the fixed bearing mount flipped self.left_bearing_mount = self.ball_screw_model.floatingBearingHoles( self.left_bearing_mount ) points = [(40 * (i - 5.5), y) for i in range(12) for y in [-18, 18]] points += [ (8 * i + j, y) for i in range(-2, 3) for y in [-18, 18] for j in [column_spacing / 2, -column_spacing / 2] ] top_w = cq.Workplane().copyWorkplane(self.upper_front_plate) bot_w = cq.Workplane().copyWorkplane(self.lower_front_plate) def holes(w, ref): return w.copyWorkplane(ref).pushPoints(points).hole(3) self.upper_front_plate = holes(self.upper_front_plate, top_w) self.upper_back_plate = holes(self.upper_back_plate, top_w) # self.upper = top_holes(self.upper) self.lower_front_plate = holes(self.lower_front_plate, bot_w) self.lower_back_plate = holes(self.lower_back_plate, bot_w) # self.lower = top_holes(self.lower) stepper_mount_w = w.transformed( offset=( column_spacing / 2 + tube_w / 2, ballscrew_x_offset, (upper_center + lower_center) / 2, ), rotate=(0, 90, 0), ) self.stepper_mount = ( cq.Workplane() .copyWorkplane( stepper_mount_w.transformed(offset=(0, 0, 0), rotate=(0, 0, 45)) ) .tag("base") .rect(58.4, 58.4) .extrude(stepper_mount_z) .copyWorkplane( stepper_mount_w.transformed(offset=(0, -ballscrew_x_offset, 0)) ) .rect(88, tube_h) .extrude(stepper_mount_z) .copyWorkplane( stepper_mount_w.transformed(offset=(0, 0, 0), rotate=(180, 0, 45)) ) .rect(47.41, 47.41, forConstruction=True) .vertices() .hole(5) .copyWorkplane( stepper_mount_w.transformed(offset=(0, 0, 0), rotate=(180, 0, 0)) ) .hole(32) # .copyWorkplane(stepper_mount_w) # .circle(40) # .extrude(10) ) self.stepper_mount = self.ball_screw_model.fixedBearingHoles(self.stepper_mount) def stepper_mount_holes(w): return ( w.copyWorkplane( stepper_mount_w.transformed(offset=(0, -ballscrew_x_offset, 5)) ) .rect(78, 26) .vertices() .hole(5) ) self.stepper_mount = stepper_mount_holes(self.stepper_mount) self.right = stepper_mount_holes(self.right) self.right_bearing_mount = stepper_mount_holes(self.right_bearing_mount) self.combined_front_plate = ( cq.Workplane() .copyWorkplane( w.transformed( offset=( column_spacing / 2, tube_h / 2, (upper_center + lower_center) / 2, ), rotate=(-90, 0, 0), ) ) .rect(20, upper_center - lower_center - tube_w + 5) .extrude(plate_z) .union(self.upper_front_plate) .union(self.lower_front_plate) ) def assembly(self): return ( cq.Assembly(name="gantry") .add(self.left, name="left column") .add(self.right, name="right column") .add(self.upper, name="upper platform") .add(self.lower, name="lower platform") .add(self.upper_rail.rail(), name="upper rail") .add(self.lower_rail.rail(), name="lower rail") .add(self.upper_front_plate, name="upper front plate") .add(self.lower_front_plate, name="lower front plate") .add(self.upper_back_plate, name="upper back plate") .add(self.lower_back_plate, name="lower back plate") .add(self.ball_screw, name="ball screw") .add(self.fixed_bearing, name="fixed bearing") .add(self.floating_bearing, name="floating bearing") .add(self.right_bearing_mount, name="fixed bearing mount") .add(self.left_bearing_mount, name="floating bearing mount") .add(self.stepper_mount, name="stepper mount") .add(self.combined_front_plate, name="combined front plate") ) z_rail_spacing = 110 z_carriage_spacing = 100 z_rail_len = 400 carriage_w = 250 carriage_h = 300 bolster_w = 30 bolster_z = 25 z_spacer_z = inch(3 / 8) # 10 z_spacer_w = 40 z_ballscrew_len = 400 z_ballscrew_offset = 0 class Carriage: def __init__(self, gantry, x=0, z=0): self.z = z self.bul = gantry.upper_rail.carriage(x) self.bur = gantry.upper_rail.carriage(x + x_carriage_spacing) self.bll = gantry.lower_rail.carriage(x) self.blr = gantry.lower_rail.carriage(x + x_carriage_spacing) back = cq.Workplane("XZ").copyWorkplane( self.bul.workplaneFromTagged("mountingholes") ) # why doesn't this track the carriage without me adding x to it? self.plate = ( cq.Workplane() .copyWorkplane(back) .center(-x - HGR20.L - x_carriage_spacing / 2, -x_rail_spacing / 2) .tag("base") # .rect(HGR20.L+x_carriage_spacing, HGR20.W+x_rail_spacing) .rect(carriage_w, carriage_h) .extrude(plate_z2) .faces(">z") # localselectors plugin .workplane() .tag("carriage_plate") ) self.plate = gantry.upper_rail.carriageHoles(self.plate, x) self.plate = gantry.upper_rail.carriageHoles(self.plate, x + x_carriage_spacing) self.plate = gantry.lower_rail.carriageHoles(self.plate, x) self.plate = gantry.lower_rail.carriageHoles(self.plate, x + x_carriage_spacing) # creating the workplane the rails of the spindle carrier # mount to, because HGR works from that plane forward self.carrier_plane = ( cq.Workplane() .copyWorkplane(self.plate.workplaneFromTagged("carriage_plate")) .transformed(offset=(0, 0, HGR20.H), rotate=(180, 0, 0)) ) self.left_rail = HGR20( self.carrier_plane.transformed( offset=(z_rail_spacing / 2, z, 0), rotate=(0, 0, 90) ), z_rail_len, ) self.right_rail = HGR20( self.carrier_plane.transformed( offset=(-z_rail_spacing / 2, z, 0), rotate=(0, 0, 90) ), z_rail_len, ) u_zcarriage_pos = z_rail_len / 2 - HGR20.L / 2 - z - z_carriage_spacing / 2 l_zcarriage_pos = u_zcarriage_pos + z_carriage_spacing self.ful = self.left_rail.carriage(u_zcarriage_pos) self.fll = self.left_rail.carriage(l_zcarriage_pos) self.fur = self.right_rail.carriage(u_zcarriage_pos) self.flr = self.right_rail.carriage(l_zcarriage_pos) self.plate = self.left_rail.carriageHoles(self.plate, u_zcarriage_pos) self.plate = self.left_rail.carriageHoles(self.plate, l_zcarriage_pos) self.plate = self.right_rail.carriageHoles(self.plate, u_zcarriage_pos) self.plate = self.right_rail.carriageHoles(self.plate, l_zcarriage_pos) self.ball_nut = gantry.ball_screw_model.nut(x + carriage_w / 2) lbolster_w = self.plate.workplaneFromTagged("carriage_plate").transformed( offset=(-(carriage_w - bolster_w) / 2, 0, 0) ) rbolster_w = self.plate.workplaneFromTagged("carriage_plate").transformed( offset=((carriage_w - bolster_w) / 2, 0, 0) ) points = [(0, 50 * (i - 2.5)) for i in range(6)] self.lbolster = ( cq.Workplane() .copyWorkplane(lbolster_w) .rect(bolster_w, carriage_h) .extrude(bolster_z) .copyWorkplane(lbolster_w.transformed(rotate=(0, 180, 0))) .pushPoints(points) .hole(3) ) self.rbolster = ( cq.Workplane() .copyWorkplane(rbolster_w) .rect(bolster_w, carriage_h) .extrude(bolster_z) .copyWorkplane(rbolster_w.transformed(rotate=(0, 180, 0))) .pushPoints(points) .hole(3) ) self.plate = ( self.plate.copyWorkplane(lbolster_w) .pushPoints(points) .hole(3) .copyWorkplane(rbolster_w) .pushPoints(points) .hole(3) ) self.wp_carrier = ( cq.Workplane() .copyWorkplane(self.plate.workplaneFromTagged("carriage_plate")) .transformed(offset=(0, -z, HGR20.H), rotate=(0, 0, 0)) ) self.x_nut_mount = ( cq.Workplane() .copyWorkplane(back) .center(-x - HGR20.L - x_carriage_spacing / 2, -x_rail_spacing / 2) .transformed(rotate=(180, 0, 0)) .rect(60, 60) .extrude(64 - 8) .faces(">z") .rect(60, 32) .extrude(8) ) self.x_nut_mount = gantry.ball_screw_model.nutHoles( self.x_nut_mount, x + carriage_w / 2 ) self.x_nut_mount = self.x_nut_mount.copyWorkplane( gantry.ball_screw_model.w.transformed( offset=(0, x + carriage_w / 2, 0), rotate=(90, 0, 0) ), ).hole(14) def nut_mount_holes(s, forward=True): return ( s.copyWorkplane(back) .center(-x - HGR20.L - x_carriage_spacing / 2, -x_rail_spacing / 2) .transformed(rotate=(0 if forward else 180, 0, 0)) .rect(48, 48) .vertices() .hole(5) ) self.x_nut_mount = nut_mount_holes(self.x_nut_mount) self.plate = nut_mount_holes(self.plate, forward=False) # these are filled in by the carrier self.z_nut_mount = None self.z_nut = None def assembly(self): assmbly = ( cq.Assembly(name="x carriage") .add(self.bul, name="back ul carriage") .add(self.bur, name="back ur carriage") .add(self.bll, name="back ll carriage") .add(self.blr, name="back lr carriage") .add(self.plate, name="carrier plate") .add(self.left_rail.rail(), name="left rail") .add(self.right_rail.rail(), name="right rail") .add(self.ful, name="front ul carriage") .add(self.fur, name="front ur carriage") .add(self.fll, name="front ll carriage") .add(self.flr, name="front lr carriage") .add(self.lbolster, name="left bolster") .add(self.rbolster, name="right bolster") .add(self.ball_nut, name="ball nut") .add(self.x_nut_mount, name="x nut mount") ) if self.z_nut_mount is not None: assmbly = assmbly.add(self.z_nut_mount, name="z nut mount") if self.z_nut is not None: assmbly = assmbly.add(self.z_nut, name="z nut") return assmbly class Carrier: def __init__(self, carriage, z): self.plane = carriage.wp_carrier self.left_spacer = ( cq.Workplane() .copyWorkplane(self.plane) .transformed(offset=(z_rail_spacing / 2, 0, 0)) .tag("base") .rect(z_spacer_w, z_rail_len) .extrude(z_spacer_z) ) self.right_spacer = ( cq.Workplane() .copyWorkplane(self.plane) .transformed(offset=(-z_rail_spacing / 2, 0, 0)) .tag("base") .rect(z_spacer_w, z_rail_len) .extrude(z_spacer_z) ) self.plate = ( cq.Workplane() .copyWorkplane(self.plane) .transformed(offset=(0, 0, z_spacer_z)) .tag("base") .rect(200, z_rail_len) .extrude(carrier_plate_z) .copyWorkplane(self.plane) .center(0, z_rail_len / 2 - 40 / 2) .rect(68, 40) .extrude(20, combine="s") ) self.plate = carriage.left_rail.holes(self.plate) self.plate = carriage.right_rail.holes(self.plate) self.left_spacer = carriage.left_rail.holes(self.left_spacer) self.right_spacer = carriage.right_rail.holes(self.right_spacer) self.ballscrew_model = SFU1204( self.plane.transformed( offset=( 0, z_ballscrew_len / 2 + 20, # 25, z_spacer_z - 25 + 5, # offset into the spindle plate 5mm ), # -(HGR20.H - z_spacer_z) / 2 - 1.2), rotate=(180, 0, 0), ), z_ballscrew_len, ) self.ballscrew = self.ballscrew_model.ballscrew() self.fixed_bearing = self.ballscrew_model.fixedBearing() self.floating_bearing = self.ballscrew_model.floatingBearing() angle_z = 0.188 * 25.4 angle_w = 2.0 * 25.4 self.stepper_bracket = ( cq.Workplane() .copyWorkplane(self.plane) .transformed(offset=(-200 / 2, z_rail_len / 2, 0), rotate=(0, 90, 0)) .sketch() .push([(-10 - 10 - angle_z + angle_w / 2, angle_z / 2 + 5)]) .rect(angle_w, angle_z) .push([(-10 - 10 - angle_z / 2, 5 + angle_z - angle_w / 2)]) .rect(angle_z, angle_w) .finalize() .extrude(200) ) self.stepper_bracket = carriage.left_rail.holes(self.stepper_bracket) self.stepper_bracket = carriage.right_rail.holes(self.stepper_bracket) self.stepper_bracket = ( self.stepper_bracket.copyWorkplane( self.ballscrew_model.w.transformed(rotate=(90, 0, 0)) ).hole(32) # .copyWorkplane(self.ballscrew_model.w.transformed(rotate=(90, 0, 0))) # .pushPoints([(40, 0)]) # .hole(5) ) self.stepper_bracket = self.ballscrew_model.fixedBearingHoles( self.stepper_bracket ) offset = ( self.ballscrew_model.w.vertices().val() - self.plane.transformed( offset=(0, z_rail_len / 2 + 10, 0), rotate=(-90, 0, 0) ) .vertices() .val() ) # print("offset: ", offset) self.stepper_mount = ( cq.Workplane() .copyWorkplane( self.plane.transformed( offset=(0, z_rail_len / 2 + 10, 0), rotate=(-90, 0, 0) ) ) .tag("base") .tag("flange_center") .rect(100, 50) .extrude(stepper_mount_z) .workplaneFromTagged("flange_center") .transformed(rotate=(180, 0, 0)) .rect(90, 25, forConstruction=True) .vertices() .hole(5) .copyWorkplane( self.plane.transformed( offset=(0, z_rail_len / 2 + 10, 0), rotate=(-90, 0, 0) ).transformed(offset=(0, -offset.y, 0), rotate=(0, 0, 45)) ) .tag("stepper_center") .rect(58.4, 58.4) .extrude(stepper_mount_z) .workplaneFromTagged("stepper_center") .transformed(rotate=(180, 0, 0)) .rect(47.41, 47.41, forConstruction=True) .vertices() .hole(5) .copyWorkplane(self.ballscrew_model.w.transformed(rotate=(90, 0, 0))) .hole(32) ) self.stepper_bracket = ( self.stepper_bracket.copyWorkplane( self.stepper_mount.workplaneFromTagged("stepper_center") ) .rect(47.41, 47.41, forConstruction=True) .vertices() .hole(5) .copyWorkplane(self.stepper_mount.workplaneFromTagged("flange_center")) .transformed(rotate=(0, 0, 0)) .rect(90, 25, forConstruction=True) .vertices() .hole(5) ) self.stepper_lower_spacer = ( cq.Workplane() .copyWorkplane(self.fixed_bearing.workplaneFromTagged("mounting face")) .rect(60, 40) .extrude(16) .copyWorkplane(self.ballscrew_model.w.transformed(rotate=(90, 0, 0))) .rect(36, 36) .cutThruAll() ) self.stepper_lower_spacer = self.ballscrew_model.fixedBearingHoles( self.stepper_lower_spacer ) self.stepper_mount = self.ballscrew_model.fixedBearingHoles(self.stepper_mount) def bracket_mounting_holes(s): points = [ (x, y) for x in [-93, -83, 93, 83] for y in [-z_ballscrew_len / 2 + 30, -z_ballscrew_len / 2 + 10] ] return ( s.copyWorkplane(self.plane.transformed(rotate=(180, 0, 0))) .pushPoints(points) .hole(5) ) self.plate = bracket_mounting_holes(self.plate) self.stepper_bracket = bracket_mounting_holes(self.stepper_bracket) ballscrew_offset = z_ballscrew_len / 2 + carriage.z / 2 - z carriage.z_nut = self.ballscrew_model.nut(ballscrew_offset) carriage.z_nut_mount = ( cq.Workplane() .copyWorkplane(carriage.plate.workplaneFromTagged("carriage_plate")) .rect(60, 60) .extrude(28) .faces(">z") .rect(32, 60) .extrude(8) .copyWorkplane( carriage.plate.workplaneFromTagged("carriage_plate").transformed( rotate=(180, 0, 0) ) ) .rect( 48, 48 ) # mounting holes; these need to line up with the x nut mounting holes .vertices() .hole(5) .copyWorkplane( self.ballscrew_model.w.transformed( offset=(0, ballscrew_offset, 0), rotate=(90, 0, 0) ), ) .hole(14) # hole for ballscrew ) carriage.z_nut_mount = self.ballscrew_model.nutHoles( carriage.z_nut_mount, ballscrew_offset ) def assembly(self): return ( cq.Assembly(name="z carrier") .add(self.left_spacer, name="left spacer") .add(self.right_spacer, name="right spacer") .add(self.plate, name="z plate") .add(self.ballscrew, name="z ballscrew") .add(self.fixed_bearing, name="z fixed bearing") # .add(self.floating_bearing, name="z floating bearing") .add(self.stepper_bracket, name="stepper motor-ballscrew bracket") .add(self.stepper_lower_spacer, name="stepper motor lower spacer") .add(self.stepper_mount, name="stepper mount") ) class SpindleMount: def __init__(self, carrier, z_offset=0): self.plane = ( carrier.plane.transformed(offset=(0, z_offset, z_spacer_z + 10)) .transformed(rotate=(-90, 0, 0)) .transformed(rotate=(0, 0, 180)) ) self.spindleaxis = cq.Workplane().copyWorkplane(self.plane).center(0, 54) self.mount_points = [(x, y) for x in [-85, 85] for y in [60, 40, 20]] self.mount = ( cq.Workplane() .copyWorkplane(self.plane) .hLineTo(184 / 2) .vLineTo(17) .hLineTo(113 / 2) .vLineTo(82) .hLineTo(-113 / 2) .vLineTo(17) .hLineTo(-184 / 2) .vLineTo(0) .close() .extrude(78) .copyWorkplane(self.spindleaxis) .cylinder(78, 104 / 2, angle=180, centered=[True, True, False]) .copyWorkplane(self.spindleaxis) .cylinder(78, 80 / 2, centered=[True, True, False], combine="s") .copyWorkplane( carrier.plane.transformed( offset=(0, z_offset, z_spacer_z + 10), rotate=(0, 180, 0) ) ) .tag("mounting_plane") .pushPoints(self.mount_points) .hole(6) ) def mounting_holes(self, w): return ( w.copyWorkplane( self.mount.workplaneFromTagged("mounting_plane").transformed( rotate=(180, 0, 0) ) ) .pushPoints(self.mount_points) .hole(6) ) def assembly(self): return cq.Assembly(name="spindle motor mount").add(self.mount, name="mount") g = Gantry(cq.Workplane()) c = Carriage(g, 150, -50) ca = Carrier(c, -50) m = SpindleMount(ca, -200) m2 = SpindleMount(ca, -200 + 80) m3 = SpindleMount(ca, -200 + 160) m4 = SpindleMount(ca, -200 + 240) m5 = SpindleMount(ca, -200 + 320) ca.plate = m.mounting_holes(ca.plate) ca.plate = m2.mounting_holes(ca.plate) ca.plate = m3.mounting_holes(ca.plate) ca.plate = m4.mounting_holes(ca.plate) ca.plate = m5.mounting_holes(ca.plate) # TODO add ball screws and associated assembly full_assembly = ( cq.Assembly() .add(g.assembly(), name="gantry") .add(c.assembly(), name="carriage") .add(ca.assembly(), name="carrier") .add(m.assembly(), name="spindle mount") ) if __name__ == "__main__": show_object(full_assembly) # show_object(ca.assembly()) # show_object(c.assembly()) # show_object(g.assembly())