def threadAsm(uplift, thredID, thredThik, pitch, starts, turns, extern): '''Return an assembly for an internal or external thread of given inner diameter, thickness, and pitch, with specified number of starts (independent thread parts), wrapping a given number of turns. uplift = Z-axis translation amount. Inner diameter thredID is the diameter of the cylinder the threads wrap against. It is that cylinder's outer diameter for external threads, or the cylinder's inner diameter for internal threads. threadAsm adds or subtracts an epsilon (0.0001) to prevent small gaps between thread and cylinder, which if they happen will lead to rendering/slicing error messages. ''' inRadi, eps, thredSpan = thredID/2, 1e-4, pitch*turns # Set tooth_height and tooth_depth in thread-shape thredShape = default_thread_section((pitch/starts)-eps, thredThik) # Generate one thread start, with eps to ensure not non-manifold inRadiEps = inRadi - (eps if extern else -eps) thred1 = thread(thredShape, inRadiEps, pitch, thredSpan, external=extern, segments_per_rot=40, neck_in_degrees=30, neck_out_degrees=30) thred = thred1 # Rotate thred1 for other thread starts for t in range(1,starts): thred += rotate(a=(0, 0, (t*360)/starts))(thred1) # Return thread moved up to proper position return up(uplift)(thred)
def assembly(): section = screw_thread.default_thread_section( tooth_height=10, tooth_depth=5) s = screw_thread.thread( outline_pts=section, inner_rad = inner_rad, pitch= screw_height, length=screw_height, segments_per_rot=SEGMENTS) #, neck_in_degrees=90, neck_out_degrees=90) c = cylinder( r=inner_rad, h=screw_height ) return s + c
def test_thread_internal( self): tooth_height = 10 tooth_depth = 5 outline = default_thread_section( tooth_height=tooth_height, tooth_depth=tooth_depth) actual_obj = thread( outline_pts=outline, inner_rad=20, pitch=2*tooth_height, length=2*tooth_height, external=False, segments_per_rot=4,neck_in_degrees=0, neck_out_degrees=0) actual = scad_render( actual_obj) expected = '\n\nrender() {\n\tintersection() {\n\t\tpolyhedron(points = [[20.0000000000, 0.0000000000, -5.0000000000], [15.0000000000, 0.0000000000, 0.0000000000], [20.0000000000, 0.0000000000, 5.0000000000], [0.0000000000, 20.0000000000, 0.0000000000], [0.0000000000, 15.0000000000, 5.0000000000], [0.0000000000, 20.0000000000, 10.0000000000], [-20.0000000000, 0.0000000000, 5.0000000000], [-15.0000000000, 0.0000000000, 10.0000000000], [-20.0000000000, 0.0000000000, 15.0000000000], [-0.0000000000, -20.0000000000, 10.0000000000], [-0.0000000000, -15.0000000000, 15.0000000000], [-0.0000000000, -20.0000000000, 20.0000000000]], triangles = [[0, 1, 3], [1, 4, 3], [1, 2, 4], [2, 5, 4], [0, 5, 2], [0, 3, 5], [3, 4, 6], [4, 7, 6], [4, 5, 7], [5, 8, 7], [3, 8, 5], [3, 6, 8], [6, 7, 9], [7, 10, 9], [7, 8, 10], [8, 11, 10], [6, 11, 8], [6, 9, 11], [0, 2, 1], [9, 10, 11]]);\n\t\tcylinder($fn = 4, h = 20, r = 20);\n\t}\n}' self.assertEqual( expected, actual)
def test_thread( self): tooth_height = 10 tooth_depth = 5 outline = default_thread_section( tooth_height=tooth_height, tooth_depth=tooth_depth) actual_obj = thread( outline_pts=outline, inner_rad=20, pitch=2*tooth_height, length=2*tooth_height, segments_per_rot=4, neck_in_degrees=0, neck_out_degrees=0) actual = scad_render( actual_obj) expected = '\n\nrender() {\n\tdifference() {\n\t\tpolyhedron(points = [[20.0000000000, 0.0000000000, -5.0000000000], [25.0000000000, 0.0000000000, 0.0000000000], [20.0000000000, 0.0000000000, 5.0000000000], [0.0000000000, 20.0000000000, 0.0000000000], [0.0000000000, 25.0000000000, 5.0000000000], [0.0000000000, 20.0000000000, 10.0000000000], [-20.0000000000, 0.0000000000, 5.0000000000], [-25.0000000000, 0.0000000000, 10.0000000000], [-20.0000000000, 0.0000000000, 15.0000000000], [-0.0000000000, -20.0000000000, 10.0000000000], [-0.0000000000, -25.0000000000, 15.0000000000], [-0.0000000000, -20.0000000000, 20.0000000000]], triangles = [[0, 1, 3], [1, 4, 3], [1, 2, 4], [2, 5, 4], [0, 5, 2], [0, 3, 5], [3, 4, 6], [4, 7, 6], [4, 5, 7], [5, 8, 7], [3, 8, 5], [3, 6, 8], [6, 7, 9], [7, 10, 9], [7, 8, 10], [8, 11, 10], [6, 11, 8], [6, 9, 11], [0, 2, 1], [9, 10, 11]]);\n\t\tunion() {\n\t\t\ttranslate(v = [0, 0, -5]) {\n\t\t\t\tcylinder(h = 30, r = 20);\n\t\t\t}\n\t\t\ttranslate(v = [0, 0, -25]) {\n\t\t\t\tcube(center = true, size = 50);\n\t\t\t}\n\t\t\ttranslate(v = [0, 0, 45]) {\n\t\t\t\tcube(center = true, size = 50);\n\t\t\t}\n\t\t}\n\t}\n}' self.assertEqual( expected, actual)
def test_thread( self): tooth_height = 10 tooth_depth = 5 outline = default_thread_section( tooth_height=tooth_height, tooth_depth=tooth_depth) actual_obj = thread( outline_pts=outline, inner_rad=20, pitch=tooth_height, length=0.75*tooth_height, segments_per_rot=SEGMENTS, neck_in_degrees=45, neck_out_degrees=45) actual = scad_render( actual_obj) expected = '\n\nrender() {\n\tintersection() {\n\t\tpolyhedron(points = [[14.9900000000, 0.0000000000, -5.0000000000], [19.9900000000, 0.0000000000, 0.0000000000], [14.9900000000, 0.0000000000, 5.0000000000], [14.1421356237, 14.1421356237, -3.7500000000], [17.6776695297, 17.6776695297, 1.2500000000], [14.1421356237, 14.1421356237, 6.2500000000], [0.0000000000, 20.0000000000, -2.5000000000], [0.0000000000, 25.0000000000, 2.5000000000], [0.0000000000, 20.0000000000, 7.5000000000], [-14.1421356237, 14.1421356237, -1.2500000000], [-17.6776695297, 17.6776695297, 3.7500000000], [-14.1421356237, 14.1421356237, 8.7500000000], [-20.0000000000, 0.0000000000, 0.0000000000], [-25.0000000000, 0.0000000000, 5.0000000000], [-20.0000000000, 0.0000000000, 10.0000000000], [-14.1421356237, -14.1421356237, 1.2500000000], [-17.6776695297, -17.6776695297, 6.2500000000], [-14.1421356237, -14.1421356237, 11.2500000000], [-0.0000000000, -14.9900000000, 2.5000000000], [-0.0000000000, -19.9900000000, 7.5000000000], [-0.0000000000, -14.9900000000, 12.5000000000]], triangles = [[0, 1, 3], [1, 4, 3], [1, 2, 4], [2, 5, 4], [0, 5, 2], [0, 3, 5], [3, 4, 6], [4, 7, 6], [4, 5, 7], [5, 8, 7], [3, 8, 5], [3, 6, 8], [6, 7, 9], [7, 10, 9], [7, 8, 10], [8, 11, 10], [6, 11, 8], [6, 9, 11], [9, 10, 12], [10, 13, 12], [10, 11, 13], [11, 14, 13], [9, 14, 11], [9, 12, 14], [12, 13, 15], [13, 16, 15], [13, 14, 16], [14, 17, 16], [12, 17, 14], [12, 15, 17], [15, 16, 18], [16, 19, 18], [16, 17, 19], [17, 20, 19], [15, 20, 17], [15, 18, 20], [0, 2, 1], [18, 19, 20]]);\n\t\tdifference() {\n\t\t\tcylinder($fn = 8, h = 7.5000000000, r = 25.0100000000);\n\t\t\tcylinder($fn = 8, h = 7.5000000000, r = 20);\n\t\t}\n\t}\n}' self.assertEqual( expected, actual)
def test_thread_internal( self): tooth_height = 10 tooth_depth = 5 outline = default_thread_section( tooth_height=tooth_height, tooth_depth=tooth_depth) actual_obj = thread( outline_pts=outline, inner_rad=20, pitch=2*tooth_height, length=2*tooth_height, segments_per_rot=SEGMENTS, neck_in_degrees=45, neck_out_degrees=45, external=False) actual = scad_render( actual_obj) expected = '\n\nrender() {\n\tintersection() {\n\t\tpolyhedron(points = [[25.0100000000, 0.0000000000, -5.0000000000], [20.0100000000, 0.0000000000, 0.0000000000], [25.0100000000, 0.0000000000, 5.0000000000], [14.1421356237, 14.1421356237, -2.5000000000], [10.6066017178, 10.6066017178, 2.5000000000], [14.1421356237, 14.1421356237, 7.5000000000], [0.0000000000, 20.0000000000, 0.0000000000], [0.0000000000, 15.0000000000, 5.0000000000], [0.0000000000, 20.0000000000, 10.0000000000], [-14.1421356237, 14.1421356237, 2.5000000000], [-10.6066017178, 10.6066017178, 7.5000000000], [-14.1421356237, 14.1421356237, 12.5000000000], [-20.0000000000, 0.0000000000, 5.0000000000], [-15.0000000000, 0.0000000000, 10.0000000000], [-20.0000000000, 0.0000000000, 15.0000000000], [-14.1421356237, -14.1421356237, 7.5000000000], [-10.6066017178, -10.6066017178, 12.5000000000], [-14.1421356237, -14.1421356237, 17.5000000000], [-0.0000000000, -20.0000000000, 10.0000000000], [-0.0000000000, -15.0000000000, 15.0000000000], [-0.0000000000, -20.0000000000, 20.0000000000], [14.1421356237, -14.1421356237, 12.5000000000], [10.6066017178, -10.6066017178, 17.5000000000], [14.1421356237, -14.1421356237, 22.5000000000], [25.0100000000, -0.0000000000, 15.0000000000], [20.0100000000, -0.0000000000, 20.0000000000], [25.0100000000, -0.0000000000, 25.0000000000]], triangles = [[0, 1, 3], [1, 4, 3], [1, 2, 4], [2, 5, 4], [0, 5, 2], [0, 3, 5], [3, 4, 6], [4, 7, 6], [4, 5, 7], [5, 8, 7], [3, 8, 5], [3, 6, 8], [6, 7, 9], [7, 10, 9], [7, 8, 10], [8, 11, 10], [6, 11, 8], [6, 9, 11], [9, 10, 12], [10, 13, 12], [10, 11, 13], [11, 14, 13], [9, 14, 11], [9, 12, 14], [12, 13, 15], [13, 16, 15], [13, 14, 16], [14, 17, 16], [12, 17, 14], [12, 15, 17], [15, 16, 18], [16, 19, 18], [16, 17, 19], [17, 20, 19], [15, 20, 17], [15, 18, 20], [18, 19, 21], [19, 22, 21], [19, 20, 22], [20, 23, 22], [18, 23, 20], [18, 21, 23], [21, 22, 24], [22, 25, 24], [22, 23, 25], [23, 26, 25], [21, 26, 23], [21, 24, 26], [0, 2, 1], [24, 25, 26]]);\n\t\tcylinder($fn = 8, h = 20, r = 20);\n\t}\n}' self.assertEqual( expected, actual)
def assembly(): section = screw_thread.default_thread_section(tooth_height=10, tooth_depth=5) s = screw_thread.thread(outline_pts=section, inner_rad=inner_rad, pitch=screw_height, length=screw_height, segments_per_rot=SEGMENTS) #, neck_in_degrees=90, neck_out_degrees=90) c = cylinder(r=inner_rad, h=screw_height) return s + c
def sfu1204_screw(l, show_thread=False): thread_len = l - 15 - 39 - 10 if show_thread: section = screw_thread.default_thread_section(tooth_height=6, tooth_depth=1) s = screw_thread.thread(outline_pts=section, inner_rad=10.0 / 2, pitch=4.0, length=thread_len, segments_per_rot=12) else: s = cylinder(r=12.0 / 2, h=thread_len) u = union()(cylinder(r=8.0 / 2, h=l), translate([0.0, 0.0, 15.0])(cylinder(r=10.0 / 2, h=l - 15 - 10)), translate([0, 0, 15.0 + 39.0])(s)) return color(Steel)(u)
def cuff_bottom_disc(gap=0, reverse=False): # plastic_battery_hole_diameter/2 inner_rad = plastic_battery_hole_diameter / 2 - pcb_gap section = screw_thread.default_thread_section(tooth_height=tooth_height, tooth_depth=tooth_depth) s = screw_thread.thread(outline_pts=section, inner_rad=inner_rad, pitch=tooth_pitch, length=plastic_top_screw_height, segments_per_rot=SEGMENTS, neck_in_degrees=30, neck_out_degrees=30) c = cylinder(r=plastic_battery_hole_diameter / 2 - pcb_gap, h=plastic_top_screw_height) h = up(plastic_top_screw_height / 2)(cylinder( r=plastic_battery_hole_diameter / 2 - pcb_gap - min_wall_free, h=plastic_top_screw_height / 2)) print plastic_battery_hole_diameter / 2 - pcb_gap - min_wall_free return c + s - h
def plastic_connector_top(gap=0, reverse=False): inner_rad = plastic_connector_dia / 2 - gap section = screw_thread.default_thread_section(tooth_height=tooth_height, tooth_depth=tooth_depth) s = screw_thread.thread(outline_pts=section, inner_rad=inner_rad, pitch=tooth_pitch, length=plastic_top_screw_height, segments_per_rot=SEGMENTS, neck_in_degrees=30, neck_out_degrees=30) c = cylinder(r=inner_rad + .05, h=plastic_top_screw_height) if reverse == False: top = s + c else: top = up(pcb_gap / 2)(cylinder(r=top_outside_diameter / 2, h=plastic_top_screw_height - pcb_gap)) top = top - (s + c) top = down(plastic_top_screw_height / 2 + pcb_thickness)(top) return up(top_height - min_wall_free - touch_pads_height - pcb_thickness)(top)
def test_default_thread_section(self): expected = [[0, -5], [5, 0], [0, 5]] actual = default_thread_section(tooth_height=10, tooth_depth=5) self.assertEqual(expected, actual)
def setUp(self): self.tooth_height = 10 self.tooth_depth = 5 self.outline = default_thread_section(tooth_height=self.tooth_height, tooth_depth=self.tooth_depth)