11#! /usr/bin/env python
22# -*- coding: utf-8 -*-
3- import os , sys , re
3+ import os
4+ import sys
5+ import re
46
57from solid import *
68from solid .utils import *
79from euclid import *
8- # NOTE: The PyEuclid on PyPi doesn't include several elements added to
10+ # NOTE: The PyEuclid on PyPi doesn't include several elements added to
911# the module as of 13 Feb 2013. Add them here until euclid supports them
1012# TODO: when euclid updates, remove this cruft. -ETJ 13 Feb 2013
1113import solid .patch_euclid
1214solid .patch_euclid .run_patch ()
1315
14- def thread (outline_pts , inner_rad , pitch , length , external = True , segments_per_rot = 32 ,neck_in_degrees = 0 , neck_out_degrees = 0 ):
16+
17+ def thread (outline_pts , inner_rad , pitch , length , external = True , segments_per_rot = 32 , neck_in_degrees = 0 , neck_out_degrees = 0 ):
1518 '''
1619 Sweeps outline_pts (an array of points describing a closed polygon in XY)
1720 through a spiral.
18-
21+
1922 This is done by creating and returning one huge polyhedron, with potentially
2023 thousands of faces. An alternate approach would make one single polyhedron,
2124 then repeat it over and over in the spiral shape, unioning them all together.
@@ -24,10 +27,10 @@ def thread(outline_pts, inner_rad, pitch, length, external=True, segments_per_ro
2427 in the python, as here. Also would take some doing to make the neck-in work
2528 as well. Not sure how the two approaches compare in terms of render-time.
2629 -ETJ 16 Mar 2011
27-
30+
2831 outline_pts: a list of points (NOT an OpenSCAD polygon) that define the cross
2932 section of the thread
30-
33+
3134 inner_rad: radius of cylinder the screw will wrap around
3235 pitch: height for one revolution; must be <= the height of outline_pts
3336 bounding box to avoid self-intersection
@@ -40,35 +43,35 @@ def thread(outline_pts, inner_rad, pitch, length, external=True, segments_per_ro
4043 a thickness of zero (inner_rad) to its full thickness
4144 neck_out_degrees: degrees through which outer edge of the screw thread will move from
4245 full thickness back to zero
43-
46+
4447 NOTE: if pitch is less than the or equal to the height of each tooth (outline_pts),
4548 OpenSCAD will likely crash, since the resulting screw would self-intersect
4649 all over the place. For screws with essentially no space between
4750 threads, (i.e., pitch=tooth_height), I use pitch= tooth_height+EPSILON,
4851 since pitch=tooth_height will self-intersect for rotations >=1
4952 '''
5053 a = union ()
51- rotations = float (length )/ pitch
52-
53- total_angle = 360.0 * rotations
54- up_step = float (length ) / (rotations * segments_per_rot )
54+ rotations = float (length ) / pitch
55+
56+ total_angle = 360.0 * rotations
57+ up_step = float (length ) / (rotations * segments_per_rot )
5558 # Add one to total_steps so we have total_steps *segments*
5659 total_steps = int (ceil (rotations * segments_per_rot )) + 1
57- step_angle = total_angle / (total_steps - 1 )
58-
60+ step_angle = total_angle / (total_steps - 1 )
61+
5962 all_points = []
6063 all_tris = []
61- euc_up = Vector3 ( * UP_VEC )
64+ euc_up = Vector3 (* UP_VEC )
6265 poly_sides = len (outline_pts )
63-
66+
6467 # Figure out how wide the tooth profile is
6568 min_bb , max_bb = bounding_box (outline_pts )
6669 outline_w = max_bb [0 ] - min_bb [0 ]
6770 outline_h = max_bb [1 ] - min_bb [1 ]
68-
69- min_rad = max (0 , inner_rad - outline_w - EPSILON )
71+
72+ min_rad = max (0 , inner_rad - outline_w - EPSILON )
7073 max_rad = inner_rad + outline_w + EPSILON
71-
74+
7275 # outline_pts, since they were created in 2D , are in the XY plane.
7376 # But spirals move a profile in XZ around the Z-axis. So swap Y and Z
7477 # co-ords... and hope users know about this
@@ -80,92 +83,95 @@ def thread(outline_pts, inner_rad, pitch, length, external=True, segments_per_ro
8083 p .append (0 )
8184 # [x, y, z] => [ x+inner_rad, z, y]
8285 external_mult = 1 if external else - 1
83- s = Point3 (external_mult * p [0 ], p [2 ], p [1 ]) # adding inner_rad, swapping Y & Z
86+ # adding inner_rad, swapping Y & Z
87+ s = Point3 (external_mult * p [0 ], p [2 ], p [1 ])
8488 euc_points .append (s )
85-
89+
8690 for i in range (total_steps ):
87- angle = i * step_angle
88-
89- elevation = i * up_step
91+ angle = i * step_angle
92+
93+ elevation = i * up_step
9094 if angle > total_angle :
9195 angle = total_angle
9296 elevation = length
93-
97+
9498 # Handle the neck-in radius for internal and external threads
9599 rad = inner_rad
96100 int_ext_mult = 1 if external else - 1
97101 neck_in_rad = min_rad if external else max_rad
98-
102+
99103 if angle < neck_in_degrees :
100104 rad = neck_in_rad + int_ext_mult * angle / neck_in_degrees * outline_w
101105 elif angle > total_angle - neck_in_degrees :
102- rad = neck_in_rad + int_ext_mult * (total_angle - angle )/ neck_out_degrees * outline_w
103-
106+ rad = neck_in_rad + int_ext_mult * (total_angle - angle ) / neck_out_degrees * outline_w
107+
104108 elev_vec = Vector3 (rad , 0 , elevation )
105-
109+
106110 # create new points
107111 for p in euc_points :
108- pt = (p + elev_vec ).rotate_around (axis = euc_up , theta = radians (angle ))
112+ pt = (
113+ p + elev_vec ).rotate_around (axis = euc_up , theta = radians (angle ))
109114 all_points .append (pt .as_arr ())
110-
115+
111116 # Add the connectivity information
112- if i < total_steps - 1 :
113- ind = i * poly_sides
117+ if i < total_steps - 1 :
118+ ind = i * poly_sides
114119 for j in range (ind , ind + poly_sides - 1 ):
115- all_tris .append ( [ j , j + 1 , j + poly_sides ])
116- all_tris .append ( [ j + 1 , j + poly_sides + 1 , j + poly_sides ])
117- all_tris .append ( [ ind , ind + poly_sides - 1 + poly_sides , ind + poly_sides - 1 ])
118- all_tris .append ( [ ind , ind + poly_sides , ind + poly_sides - 1 + poly_sides ])
119-
120+ all_tris .append ([j , j + 1 , j + poly_sides ])
121+ all_tris .append ([j + 1 , j + poly_sides + 1 , j + poly_sides ])
122+ all_tris .append (
123+ [ind , ind + poly_sides - 1 + poly_sides , ind + poly_sides - 1 ])
124+ all_tris .append (
125+ [ind , ind + poly_sides , ind + poly_sides - 1 + poly_sides ])
126+
120127 # End triangle fans for beginning and end
121128 last_loop = len (all_points ) - poly_sides
122- for i in range (poly_sides - 2 ):
123- all_tris .append ( [ 0 , i + 2 , i + 1 ])
124- all_tris .append ( [ last_loop , last_loop + i + 1 , last_loop + i + 2 ])
125-
126-
129+ for i in range (poly_sides - 2 ):
130+ all_tris .append ([0 , i + 2 , i + 1 ])
131+ all_tris .append ([last_loop , last_loop + i + 1 , last_loop + i + 2 ])
132+
127133 # Make the polyhedron
128134 a = polyhedron (points = all_points , faces = all_tris )
129-
135+
130136 if external :
131137 # Intersect with a cylindrical tube to make sure we fit into
132138 # the correct dimensions
133- tube = cylinder (r = inner_rad + outline_w + EPSILON , h = length , segments = segments_per_rot )
139+ tube = cylinder (
140+ r = inner_rad + outline_w + EPSILON , h = length , segments = segments_per_rot )
134141 tube -= cylinder (r = inner_rad , h = length , segments = segments_per_rot )
135142 else :
136- # If the threading is internal, intersect with a central cylinder
143+ # If the threading is internal, intersect with a central cylinder
137144 # to make sure nothing else remains
138- tube = cylinder (r = inner_rad , h = length , segments = segments_per_rot )
145+ tube = cylinder (r = inner_rad , h = length , segments = segments_per_rot )
139146 a *= tube
140147 return render ()(a )
141148
142149
143-
144150def default_thread_section (tooth_height , tooth_depth ):
145151 # An isoceles triangle, tooth_height vertically, tooth_depth wide:
146- res = [ [ 0 , - tooth_height / 2 ],
147- [ tooth_depth , 0 ],
148- [ 0 , tooth_height / 2 ]
149- ]
152+ res = [[ 0 , - tooth_height / 2 ],
153+ [ tooth_depth , 0 ],
154+ [ 0 , tooth_height / 2 ]
155+ ]
150156 return res
151157
152158
153159def assembly ():
154160 # Scad code here
155161 a = union ()
156-
162+
157163 rad = 5
158- pts = [ [ 0 , - 1 , 0 ],
159- [ 1 , 0 , 0 ],
160- [ 0 , 1 , 0 ],
161- [ - 1 , 0 , 0 ],
162- [ - 1 , - 1 , 0 ] ]
163-
164- a = thread (pts , inner_rad = 10 , pitch = 6 , length = 2 , segments_per_rot = 31 ,
165- neck_in_degrees = 30 , neck_out_degrees = 30 )
166-
167- return a + cylinder (10 + EPSILON , 2 )
164+ pts = [[ 0 , - 1 , 0 ],
165+ [ 1 , 0 , 0 ],
166+ [ 0 , 1 , 0 ],
167+ [ - 1 , 0 , 0 ],
168+ [ - 1 , - 1 , 0 ]]
169+
170+ a = thread (pts , inner_rad = 10 , pitch = 6 , length = 2 , segments_per_rot = 31 ,
171+ neck_in_degrees = 30 , neck_out_degrees = 30 )
172+
173+ return a + cylinder (10 + EPSILON , 2 )
168174
169175if __name__ == '__main__' :
170- a = assembly ()
171- scad_render_to_file (a )
176+ a = assembly ()
177+ scad_render_to_file (a )
0 commit comments