Integrated Freestyle to rendering pipeline
[blender.git] / release / scripts / wizard_bolt_factory.py
1 #!BPY
2 # -*- coding: latin-1 -*-
3 """
4 Name: 'Bolt Factory'
5 Blender: 248
6 Group: 'Wizards'
7 Tooltip: 'Create models of various types of screw fasteners.'
8 """
9
10 __author__ = " Aaron Keith (Spudmn) "
11 __version__ = "2.02 2009/06/10"
12 __url__ = ["Author's site,http://sourceforge.net/projects/boltfactory/", "Blender,http://wiki.blender.org/index.php/Extensions:Py/Scripts/Manual/Misc/Bolt_Factory"]
13 __bpydoc__ = """\
14 Bolt_Factory.py 
15
16 Bolt Factory is a Python script for Blender 3D.
17
18 The script allows the user to create models of various types of screw fasteners.
19
20 For best results set the material to smooth and apply a Edge Split modifier
21 with default settings.
22
23
24 History:
25  V2.02 10/06/09 by Aaron Keith
26
27     -Added changes made by the Blender team.
28
29  V2.01 26/05/09 by Aaron Keith
30
31     -    Fixed normal's on Lock Nut
32
33 V2.00 22/05/09 by Aaron Keith
34
35 - Better error checking.
36 - Lock Nut and Hex Nut meshes added.
37 - Pre-sets for common metric bolts and nuts.
38 - Improved GUI.
39 - Meshes scaled to a smaller size
40 - Fixed bug when using crest and root percent other than 10%
41 - Can now create meshes in Edit Mode.  This will add to the 
42   current mesh and align with the current view.
43
44 V1.00 01/04/08 by Aaron Keith
45
46 - This version is very much a work in progress.
47 - This is my first attempt to program in Python.  This version is
48   unpolished and doesn't do much error checking.  Therefore 
49   if the user sets strange variable the model created will be 
50   as equally strange.
51
52 - To Do:
53 - Better error checking.
54 - More Head and Bit types. 
55 - Better documentation.
56
57
58 """
59
60 # -------------------------------------------------------------------------- 
61 # Bolt_Factory.py 
62 # -------------------------------------------------------------------------- 
63 # ***** BEGIN GPL LICENSE BLOCK ***** 
64
65 # Copyright (C) 2009: Aaron Keith
66
67 # This program is free software; you can redistribute it and/or 
68 # modify it under the terms of the GNU General Public License 
69 # as published by the Free Software Foundation; either version 2 
70 # of the License, or (at your option) any later version. 
71
72 # This program is distributed in the hope that it will be useful, 
73 # but WITHOUT ANY WARRANTY; without even the implied warranty of 
74 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
75 # GNU General Public License for more details. 
76
77 # You should have received a copy of the GNU General Public License 
78 # along with this program; if not, write to the Free Software Foundation, 
79 # Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. 
80
81 # ***** END GPL LICENCE BLOCK ***** 
82 # -------------------------------------------------------------------------- 
83
84
85
86
87 import Blender
88 from Blender import Draw, BGL,Mesh
89 from Blender import *
90 from math import *
91 from Blender import Mathutils
92 from Blender.Mathutils import *
93
94
95 #Global_Scale = 0.001    #1 blender unit = X mm
96 Global_Scale = 0.1    #1 blender unit = X mm
97 #Global_Scale = 1.0    #1 blender unit = X mm
98 Global_NutRad = 0.0
99 MAX_INPUT_NUMBER = 50
100
101 No_Event,On_Preset_Click,On_Apply_Click,On_Create_Click,On_Hex_Click, On_Cap_Click,On_Dome_Click,On_Pan_Click,On_Bit_None_Click,On_Bit_Allen_Click,On_Bit_Philips_Click,On_Exit_Click,On_Model_Bolt_Click,On_Model_Nut_Click,On_Hex_Nut_Click,On_Lock_Nut_Click,On_Test_Click = range(17)  # this is like a ENUM
102
103
104 Head_Type={'HEX' : [Draw.Create(1),On_Hex_Click,""],
105            'CAP' : [Draw.Create(0),On_Cap_Click,""],
106            'DOME': [Draw.Create(0),On_Dome_Click,""],
107            'PAN' : [Draw.Create(0),On_Pan_Click,""]}
108
109
110 Bit_Type={'NONE' : [Draw.Create(1),On_Bit_None_Click,""],
111            'ALLEN' : [Draw.Create(0),On_Bit_Allen_Click,""],
112            'PHILLIPS': [Draw.Create(0),On_Bit_Philips_Click,""]}
113
114 Model_Type={'BOLT' : [Draw.Create(1),On_Model_Bolt_Click,"Bolt Settings"],
115            'NUT' : [Draw.Create(0),On_Model_Nut_Click,"Nut Settings"]}
116
117 Nut_Type={'HEX' : [Draw.Create(1),On_Hex_Nut_Click,""],
118            'LOCK' : [Draw.Create(0),On_Lock_Nut_Click,""]}
119
120
121 Phillips_Bit_Depth = Draw.Create(3.27)
122 Philips_Bit_Dia = Draw.Create(5.20)
123
124 Allen_Bit_Depth = Draw.Create(4.0)
125 Allen_Bit_Flat_Distance = Draw.Create(6.0)
126
127 Hex_Head_Height = Draw.Create(5.3)
128 Hex_Head_Flat_Distance = Draw.Create(13.0)
129
130 Cap_Head_Dia = Draw.Create(13.5)
131 Cap_Head_Height = Draw.Create(8.0)
132
133 Dome_Head_Dia = Draw.Create(16.0)
134
135 Pan_Head_Dia = Draw.Create(16.0)
136
137 Shank_Dia = Draw.Create(8.0)
138 Shank_Length = Draw.Create(0.0)
139
140 Thread_Length = Draw.Create(16.0)
141 Major_Dia = Draw.Create(8.0)
142 Minor_Dia = Draw.Create(6.917)
143 Pitch = Draw.Create(1.0)
144 Crest_Percent = Draw.Create(10)
145 Root_Percent = Draw.Create(10)
146
147 Hex_Nut_Height = Draw.Create(8.0)
148 Hex_Nut_Flat_Distance = Draw.Create(13.0)
149
150 Preset_Menu = Draw.Create(5)
151
152
153 ##########################################################################################
154 ##########################################################################################
155 ##                    Miscellaneous Utilities
156 ##########################################################################################
157 ##########################################################################################
158
159 # Returns a list of verts rotated by the given matrix. Used by SpinDup
160 def Rot_Mesh(verts,matrix):
161     return [list(Vector(v) * matrix) for v in verts]
162
163 # Returns a list of faces that has there index incremented by offset 
164 def Copy_Faces(faces,offset):        
165     ret = []
166     for f in faces:
167         fsub = []
168         for i in range(len(f)):
169             fsub.append(f[i]+ offset)
170         ret.append(fsub)
171     return ret
172
173
174 # Much like Blenders built in SpinDup.
175 def SpinDup(VERTS,FACES,DEGREE,DIVISIONS,AXIS):
176     verts=[]
177     faces=[]
178     
179     if DIVISIONS == 0:
180        DIVISIONS = 1  
181   
182     step = DEGREE/DIVISIONS # set step so pieces * step = degrees in arc
183     
184     for i in xrange(int(DIVISIONS)):
185         rotmat = Mathutils.RotationMatrix(step*i, 4, AXIS) # 4x4 rotation matrix, 30d about the x axis.
186         Rot = Rot_Mesh(VERTS,rotmat)
187         faces.extend(Copy_Faces(FACES,len(verts)))    
188         verts.extend(Rot)
189     return verts,faces
190
191
192 # Returns a list of verts that have been moved up the z axis by DISTANCE
193 def Move_Verts_Up_Z(VERTS,DISTANCE):
194     return [[v[0],v[1],v[2]+DISTANCE] for v in VERTS]
195
196
197 # Returns a list of verts and faces that has been mirrored in the AXIS 
198 def Mirror_Verts_Faces(VERTS,FACES,AXIS,FLIP_POINT =0):
199     ret_vert = []
200     ret_face = []
201     offset = len(VERTS)    
202     if AXIS == 'y':
203         for v in VERTS:
204             Delta = v[0] - FLIP_POINT
205             ret_vert.append([FLIP_POINT-Delta,v[1],v[2]]) 
206     if AXIS == 'x':
207         for v in VERTS:
208             Delta = v[1] - FLIP_POINT
209             ret_vert.append([v[0],FLIP_POINT-Delta,v[2]]) 
210     if AXIS == 'z':
211         for v in VERTS:
212             Delta = v[2] - FLIP_POINT
213             ret_vert.append([v[0],v[1],FLIP_POINT-Delta]) 
214             
215     for f in FACES:
216         fsub = []
217         for i in range(len(f)):
218             fsub.append(f[i]+ offset)
219         fsub.reverse() # flip the order to make norm point out
220         ret_face.append(fsub)
221             
222     return ret_vert,ret_face
223
224
225
226 # Returns a list of faces that 
227 # make up an array of 4 point polygon. 
228 def Build_Face_List_Quads(OFFSET,COLUM,ROW,FLIP = 0):
229     Ret =[]
230     RowStart = 0;
231     for j in range(ROW):
232         for i in range(COLUM):
233             Res1 = RowStart + i;
234             Res2 = RowStart + i + (COLUM +1)
235             Res3 = RowStart + i + (COLUM +1) +1
236             Res4 = RowStart+i+1
237             if FLIP:
238                 Ret.append([OFFSET+Res1,OFFSET+Res2,OFFSET+Res3,OFFSET+Res4])
239             else:
240                 Ret.append([OFFSET+Res4,OFFSET+Res3,OFFSET+Res2,OFFSET+Res1])
241         RowStart += COLUM+1
242     return Ret
243
244
245 # Returns a list of faces that makes up a fill pattern for a 
246 # circle
247 def Fill_Ring_Face(OFFSET,NUM,FACE_DOWN = 0):
248     Ret =[]
249     Face = [1,2,0]
250     TempFace = [0,0,0]
251     A = 0
252     B = 1
253     C = 2
254     if NUM < 3:
255         return None
256     for i in range(NUM-2):
257         if (i%2):
258             TempFace[0] = Face[C];
259             TempFace[1] = Face[C] + 1;
260             TempFace[2] = Face[B];
261             if FACE_DOWN:
262                 Ret.append([OFFSET+Face[2],OFFSET+Face[1],OFFSET+Face[0]])
263             else:
264                 Ret.append([OFFSET+Face[0],OFFSET+Face[1],OFFSET+Face[2]])
265         else:
266             TempFace[0] =Face[C];
267             if Face[C] == 0:
268                 TempFace[1] = NUM-1; 
269             else:
270                 TempFace[1] = Face[C] - 1;
271             TempFace[2] = Face[B];
272             if FACE_DOWN:
273                 Ret.append([OFFSET+Face[0],OFFSET+Face[1],OFFSET+Face[2]])
274             else:
275                 Ret.append([OFFSET+Face[2],OFFSET+Face[1],OFFSET+Face[0]])
276         
277         Face[0] = TempFace[0]
278         Face[1] = TempFace[1]
279         Face[2] = TempFace[2]
280     return Ret
281     
282
283 ##########################################################################################
284 ##########################################################################################
285 ##                    Converter Functions For Bolt Factory 
286 ##########################################################################################
287 ##########################################################################################
288
289
290 def Flat_To_Radius(FLAT):
291     h = (float(FLAT)/2)/cos(radians(30))
292     return h
293
294 def Get_Phillips_Bit_Height(Bit_Dia):
295     Flat_Width_half = (Bit_Dia*(0.5/1.82))/2.0
296     Bit_Rad = Bit_Dia / 2.0
297     x = Bit_Rad - Flat_Width_half
298     y = tan(radians(60))*x
299     return y 
300
301 ##########################################################################################
302 ##########################################################################################
303 ##                    Error Checking
304 ##########################################################################################
305 ##########################################################################################
306
307
308 def Error_Check():
309
310     #global Phillips_Bit_Depth 
311     #global Philips_Bit_Dia 
312
313     #global Allen_Bit_Depth 
314     #global Allen_Bit_Flat_Distance 
315
316     #global Hex_Head_Height 
317     #global Hex_Head_Flat_Distance 
318
319     #global Cap_Head_Dia 
320     #global Cap_Head_Height 
321     
322
323     #global Dome_Head_Dia 
324
325     #global Pan_Head_Dia 
326
327     #global Shank_Dia 
328     #global Shank_Length 
329
330     global Thread_Length
331     global Major_Dia 
332     global Minor_Dia 
333     global Pitch 
334     global Hex_Nut_Flat_Distance
335     global Model_Type
336     #global Crest_Percent 
337     #global Root_Percent 
338
339     Error_Result = 0
340     
341     if Minor_Dia.val >= Major_Dia.val:
342         error_txt = "Error%t|Major Dia must be larger than Minor Dia"
343         Blender.Draw.PupMenu(error_txt)
344         print error_txt
345         Error_Result = TRUE  
346
347     elif (Model_Type['BOLT'][0].val) and ((Pitch.val*7.0) > Thread_Length.val):
348         error_txt =  "Error%t|Thread length must be at least 7 times the Pitch"
349         Blender.Draw.PupMenu(error_txt)
350         print error_txt
351         Error_Result = TRUE  
352     
353     elif (Model_Type['NUT'][0].val) and (Hex_Nut_Flat_Distance.val < Major_Dia.val):
354         error_txt =  "Error%t|Nut Flat Distance must be greater than Major Dia"
355         Blender.Draw.PupMenu(error_txt)
356         print error_txt
357         Error_Result = TRUE  
358     
359     elif (Model_Type['NUT'][0].val) and ((Pitch.val * 2.5 )> Hex_Nut_Height.val):
360         error_txt =  "Error%t|Nut Height must be greater than 2.5 * Pitch"
361         Blender.Draw.PupMenu(error_txt)
362         print error_txt
363         Error_Result = TRUE  
364
365     elif (Model_Type['BOLT'][0].val):
366         Check_Head_Height = None
367         Check_Bit_Height = None
368         if (Bit_Type['ALLEN'][0].val):
369             Check_Bit_Height = Allen_Bit_Depth.val
370         if (Bit_Type['PHILLIPS'][0].val):
371             Check_Bit_Height = Phillips_Bit_Depth.val
372         if (Head_Type['HEX'][0].val):
373             Check_Head_Height = Hex_Head_Height.val
374         if (Head_Type['CAP'][0].val):
375             Check_Head_Height = Cap_Head_Height.val
376         
377         if Check_Head_Height != None and Check_Bit_Height != None :
378             if Check_Bit_Height  > Check_Head_Height:
379                 error_txt =  "Error%t|Bit Depth must not be greater that Head Height"
380                 Blender.Draw.PupMenu(error_txt)
381                 print error_txt
382                 Error_Result = TRUE
383     
384     
385     return Error_Result 
386
387
388
389 ##########################################################################################
390 ##########################################################################################
391 ##                    Create Allen Bit
392 ##########################################################################################
393 ##########################################################################################
394
395
396 def Allen_Fill(OFFSET,FLIP= 0):
397     faces = []
398     Lookup = [[19,1,0],
399               [19,2,1],
400               [19,3,2],
401               [19,20,3],
402               [20,4,3],
403               [20,5,4],
404               [20,6,5],
405               [20,7,6],
406               [20,8,7],
407               [20,9,8],
408               
409               [20,21,9],
410               
411               [21,10,9],
412               [21,11,10],
413               [21,12,11],
414               [21,13,12],
415               [21,14,13],
416               [21,15,14],
417               
418               [21,22,15],
419               [22,16,15],
420               [22,17,16],
421               [22,18,17]
422               ]
423     for i in Lookup:
424         if FLIP:
425             faces.append([OFFSET+i[2],OFFSET+i[1],OFFSET+i[0]])
426         else:
427             faces.append([OFFSET+i[0],OFFSET+i[1],OFFSET+i[2]])
428             
429     return faces
430
431 def Allen_Bit_Dia(FLAT_DISTANCE):
432     Flat_Radius = (float(FLAT_DISTANCE)/2.0)/cos(radians(30))
433     return (Flat_Radius * 1.05) * 2.0
434     
435 def Allen_Bit_Dia_To_Flat(DIA):
436     Flat_Radius = (DIA/2.0)/1.05
437     return (Flat_Radius * cos (radians(30)))* 2.0
438     
439     
440
441 def Create_Allen_Bit(FLAT_DISTANCE,HEIGHT):
442     Div = 36
443     verts = []
444     faces = []
445     
446     Flat_Radius = (float(FLAT_DISTANCE)/2.0)/cos(radians(30))
447     OUTTER_RADIUS = Flat_Radius * 1.05
448     Outter_Radius_Height = Flat_Radius * (0.1/5.77)
449     FaceStart_Outside = len(verts)
450     Deg_Step = 360.0 /float(Div)
451     
452     for i in range((Div/2)+1):    # only do half and mirror later
453         x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
454         y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
455         verts.append([x,y,0])
456     
457     FaceStart_Inside = len(verts)
458         
459     Deg_Step = 360.0 /float(6) 
460     for i in range((6/2)+1): 
461         x = sin(radians(i*Deg_Step))* Flat_Radius
462         y = cos(radians(i*Deg_Step))* Flat_Radius
463         verts.append([x,y,0-Outter_Radius_Height])     
464      
465     faces.extend(Allen_Fill(FaceStart_Outside,0))
466     
467     
468     FaceStart_Bottom = len(verts)
469     
470     Deg_Step = 360.0 /float(6) 
471     for i in range((6/2)+1): 
472         x = sin(radians(i*Deg_Step))* Flat_Radius
473         y = cos(radians(i*Deg_Step))* Flat_Radius
474         verts.append([x,y,0-HEIGHT])     
475         
476     faces.extend(Build_Face_List_Quads(FaceStart_Inside,3,1,TRUE))
477     faces.extend(Fill_Ring_Face(FaceStart_Bottom,4))
478     
479     
480     M_Verts,M_Faces = Mirror_Verts_Faces(verts,faces,'y')
481     verts.extend(M_Verts)
482     faces.extend(M_Faces)
483     
484     return verts,faces,OUTTER_RADIUS * 2.0
485
486
487 ##########################################################################################
488 ##########################################################################################
489 ##                    Create Phillips Bit
490 ##########################################################################################
491 ##########################################################################################
492
493
494 def Phillips_Fill(OFFSET,FLIP= 0):
495     faces = []
496     Lookup = [[0,1,10],
497               [1,11,10],
498               [1,2,11],
499               [2,12,11],
500               
501               [2,3,12],
502               [3,4,12],
503               [4,5,12],
504               [5,6,12],
505               [6,7,12],
506               
507               [7,13,12],
508               [7,8,13],
509               [8,14,13],
510               [8,9,14],
511               
512               
513               [10,11,16,15],
514               [11,12,16],
515               [12,13,16],
516               [13,14,17,16],
517               [15,16,17,18]
518               
519               
520               ]
521     for i in Lookup:
522         if FLIP:
523             if len(i) == 3:
524                 faces.append([OFFSET+i[2],OFFSET+i[1],OFFSET+i[0]])
525             else:    
526                 faces.append([OFFSET+i[3],OFFSET+i[2],OFFSET+i[1],OFFSET+i[0]])
527         else:
528             if len(i) == 3:
529                 faces.append([OFFSET+i[0],OFFSET+i[1],OFFSET+i[2]])
530             else:
531                 faces.append([OFFSET+i[0],OFFSET+i[1],OFFSET+i[2],OFFSET+i[3]])
532     return faces
533
534
535
536 def Create_Phillips_Bit(FLAT_DIA,FLAT_WIDTH,HEIGHT):
537     Div = 36
538     verts = []
539     faces = []
540     
541     FLAT_RADIUS = FLAT_DIA * 0.5
542     OUTTER_RADIUS = FLAT_RADIUS * 1.05
543     
544     Flat_Half = float(FLAT_WIDTH)/2.0
545         
546     FaceStart_Outside = len(verts)
547     Deg_Step = 360.0 /float(Div)
548     for i in range((Div/4)+1):    # only do half and mirror later
549         x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
550         y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
551         verts.append([x,y,0])
552     
553         
554     FaceStart_Inside = len(verts)
555     verts.append([0,FLAT_RADIUS,0]) #10
556     verts.append([Flat_Half,FLAT_RADIUS,0]) #11
557     verts.append([Flat_Half,Flat_Half,0])     #12
558     verts.append([FLAT_RADIUS,Flat_Half,0])    #13
559     verts.append([FLAT_RADIUS,0,0])            #14
560
561  
562     verts.append([0,Flat_Half,0-HEIGHT])        #15
563     verts.append([Flat_Half,Flat_Half,0-HEIGHT])    #16
564     verts.append([Flat_Half,0,0-HEIGHT])            #17
565     
566     verts.append([0,0,0-HEIGHT])            #18
567     
568     faces.extend(Phillips_Fill(FaceStart_Outside,TRUE))
569
570     Spin_Verts,Spin_Face = SpinDup(verts,faces,360,4,'z')
571    
572     return Spin_Verts,Spin_Face,OUTTER_RADIUS * 2
573     
574
575 ##########################################################################################
576 ##########################################################################################
577 ##                    Create Head Types
578 ##########################################################################################
579 ##########################################################################################
580
581 def Max_Pan_Bit_Dia(HEAD_DIA):
582     HEAD_RADIUS = HEAD_DIA * 0.5
583     XRad = HEAD_RADIUS * 1.976
584     return (sin(radians(10))*XRad) * 2.0
585
586
587 def Create_Pan_Head(HOLE_DIA,HEAD_DIA,SHANK_DIA,HEIGHT,RAD1,RAD2,FACE_OFFSET):
588
589     DIV = 36
590     HOLE_RADIUS = HOLE_DIA * 0.5
591     HEAD_RADIUS = HEAD_DIA * 0.5
592     SHANK_RADIUS = SHANK_DIA * 0.5
593
594     verts = []
595     faces = []
596     Row = 0
597     BEVEL = HEIGHT * 0.01
598     #Dome_Rad =  HEAD_RADIUS * (1.0/1.75)
599     
600     Dome_Rad = HEAD_RADIUS * 1.12
601     RAD_Offset = HEAD_RADIUS * 0.96
602     OtherRad = HEAD_RADIUS * 0.16
603     OtherRad_X_Offset = HEAD_RADIUS * 0.84
604     OtherRad_Z_Offset = HEAD_RADIUS * 0.504
605     XRad = HEAD_RADIUS * 1.976
606     ZRad = HEAD_RADIUS * 1.768
607     EndRad = HEAD_RADIUS * 0.284
608     EndZOffset = HEAD_RADIUS * 0.432
609     HEIGHT = HEAD_RADIUS * 0.59
610     
611 #    Dome_Rad =  5.6
612 #    RAD_Offset = 4.9
613 #    OtherRad = 0.8
614 #    OtherRad_X_Offset = 4.2
615 #    OtherRad_Z_Offset = 2.52
616 #    XRad = 9.88
617 #    ZRad = 8.84
618 #    EndRad = 1.42
619 #    EndZOffset = 2.16
620 #    HEIGHT = 2.95
621     
622     FaceStart = FACE_OFFSET
623
624     z = cos(radians(10))*ZRad
625     verts.append([HOLE_RADIUS,0.0,(0.0-ZRad)+z])
626     Start_Height = 0 - ((0.0-ZRad)+z)
627     Row += 1
628
629     #for i in range(0,30,10):  was 0 to 30 more work needed to make this look good.
630     for i in range(10,30,10):
631         x = sin(radians(i))*XRad
632         z = cos(radians(i))*ZRad
633         verts.append([x,0.0,(0.0-ZRad)+z])
634         Row += 1
635
636     for i in range(20,140,10):
637         x = sin(radians(i))*EndRad
638         z = cos(radians(i))*EndRad
639         if ((0.0 - EndZOffset)+z) < (0.0-HEIGHT):
640             verts.append([(HEAD_RADIUS -EndRad)+x,0.0,0.0 - HEIGHT])
641         else:
642             verts.append([(HEAD_RADIUS -EndRad)+x,0.0,(0.0 - EndZOffset)+z])
643         Row += 1
644         
645         
646     verts.append([SHANK_RADIUS,0.0,(0.0-HEIGHT)])
647     Row += 1
648     
649     verts.append([SHANK_RADIUS,0.0,(0.0-HEIGHT)-Start_Height])
650     Row += 1
651
652
653     sVerts,sFaces = SpinDup(verts,faces,360,DIV,'z')
654     sVerts.extend(verts)        #add the start verts to the Spin verts to complete the loop
655     
656     faces.extend(Build_Face_List_Quads(FaceStart,Row-1,DIV))
657
658     Global_Head_Height = HEIGHT ;
659
660     
661     return Move_Verts_Up_Z(sVerts,Start_Height),faces,HEIGHT
662
663
664
665 def Create_Dome_Head(HOLE_DIA,HEAD_DIA,SHANK_DIA,HEIGHT,RAD1,RAD2,FACE_OFFSET):
666     DIV = 36
667     HOLE_RADIUS = HOLE_DIA * 0.5
668     HEAD_RADIUS = HEAD_DIA * 0.5
669     SHANK_RADIUS = SHANK_DIA * 0.5
670     
671     verts = []
672     faces = []
673     Row = 0
674     BEVEL = HEIGHT * 0.01
675     #Dome_Rad =  HEAD_RADIUS * (1.0/1.75)
676     
677     Dome_Rad =  HEAD_RADIUS * 1.12
678     #Head_Height = HEAD_RADIUS * 0.78
679     RAD_Offset = HEAD_RADIUS * 0.98
680     Dome_Height = HEAD_RADIUS * 0.64
681     OtherRad = HEAD_RADIUS * 0.16
682     OtherRad_X_Offset = HEAD_RADIUS * 0.84
683     OtherRad_Z_Offset = HEAD_RADIUS * 0.504
684     
685     
686 #    Dome_Rad =  5.6
687 #    RAD_Offset = 4.9
688 #    Dome_Height = 3.2
689 #    OtherRad = 0.8
690 #    OtherRad_X_Offset = 4.2
691 #    OtherRad_Z_Offset = 2.52
692 #    
693     
694     FaceStart = FACE_OFFSET
695     
696     verts.append([HOLE_RADIUS,0.0,0.0])
697     Row += 1
698
699
700     for i in range(0,60,10):
701         x = sin(radians(i))*Dome_Rad
702         z = cos(radians(i))*Dome_Rad
703         if ((0.0-RAD_Offset)+z) <= 0:
704             verts.append([x,0.0,(0.0-RAD_Offset)+z])
705             Row += 1
706
707
708     for i in range(60,160,10):
709         x = sin(radians(i))*OtherRad
710         z = cos(radians(i))*OtherRad
711         z = (0.0-OtherRad_Z_Offset)+z
712         if z < (0.0-Dome_Height):
713             z = (0.0-Dome_Height)
714         verts.append([OtherRad_X_Offset+x,0.0,z])
715         Row += 1
716         
717     verts.append([SHANK_RADIUS,0.0,(0.0-Dome_Height)])
718     Row += 1
719
720
721     sVerts,sFaces = SpinDup(verts,faces,360,DIV,'z')
722     sVerts.extend(verts)        #add the start verts to the Spin verts to complete the loop
723     
724     faces.extend(Build_Face_List_Quads(FaceStart,Row-1,DIV))
725
726     return sVerts,faces,Dome_Height
727
728
729
730 def Create_Cap_Head(HOLE_DIA,HEAD_DIA,SHANK_DIA,HEIGHT,RAD1,RAD2):
731     DIV = 36
732     
733     HOLE_RADIUS = HOLE_DIA * 0.5
734     HEAD_RADIUS = HEAD_DIA * 0.5
735     SHANK_RADIUS = SHANK_DIA * 0.5
736     
737     verts = []
738     faces = []
739     Row = 0
740     BEVEL = HEIGHT * 0.01
741     
742     
743     FaceStart = len(verts)
744
745     verts.append([HOLE_RADIUS,0.0,0.0])
746     Row += 1
747
748     #rad
749     
750     for i in range(0,100,10):
751         x = sin(radians(i))*RAD1
752         z = cos(radians(i))*RAD1
753         verts.append([(HEAD_RADIUS-RAD1)+x,0.0,(0.0-RAD1)+z])
754         Row += 1
755     
756     
757     verts.append([HEAD_RADIUS,0.0,0.0-HEIGHT+BEVEL])
758     Row += 1
759
760     verts.append([HEAD_RADIUS-BEVEL,0.0,0.0-HEIGHT])
761     Row += 1
762
763     #rad2
764    
765     for i in range(0,100,10):
766         x = sin(radians(i))*RAD2
767         z = cos(radians(i))*RAD2
768         verts.append([(SHANK_RADIUS+RAD2)-x,0.0,(0.0-HEIGHT-RAD2)+z])
769         Row += 1
770     
771
772     sVerts,sFaces = SpinDup(verts,faces,360,DIV,'z')
773     sVerts.extend(verts)        #add the start verts to the Spin verts to complete the loop
774     
775
776     faces.extend(Build_Face_List_Quads(FaceStart,Row-1,DIV))
777     
778     return sVerts,faces,HEIGHT+RAD2
779
780
781
782 def Create_Hex_Head(FLAT,HOLE_DIA,SHANK_DIA,HEIGHT):
783     
784     verts = []
785     faces = []
786     HOLE_RADIUS = HOLE_DIA * 0.5
787     Half_Flat = FLAT/2
788     TopBevelRadius = Half_Flat - (Half_Flat* (0.05/8))
789     Undercut_Height = (Half_Flat* (0.05/8))
790     Shank_Bevel = (Half_Flat* (0.05/8)) 
791     Flat_Height = HEIGHT - Undercut_Height - Shank_Bevel
792     #Undercut_Height = 5
793     SHANK_RADIUS = SHANK_DIA/2
794     Row = 0;
795
796     verts.append([0.0,0.0,0.0])
797     
798     
799     FaceStart = len(verts)
800     #inner hole
801     
802     x = sin(radians(0))*HOLE_RADIUS
803     y = cos(radians(0))*HOLE_RADIUS
804     verts.append([x,y,0.0])
805     
806     
807     x = sin(radians(60/6))*HOLE_RADIUS
808     y = cos(radians(60/6))*HOLE_RADIUS
809     verts.append([x,y,0.0])
810     
811     
812     x = sin(radians(60/3))*HOLE_RADIUS
813     y = cos(radians(60/3))*HOLE_RADIUS
814     verts.append([x,y,0.0])
815     
816     
817     x = sin(radians(60/2))*HOLE_RADIUS
818     y = cos(radians(60/2))*HOLE_RADIUS
819     verts.append([x,y,0.0])
820     Row += 1
821     
822     #bevel
823     
824     x = sin(radians(0))*TopBevelRadius
825     y = cos(radians(0))*TopBevelRadius
826     vec1 = Mathutils.Vector([x,y,0.0])
827     verts.append([x,y,0.0])
828     
829     
830     x = sin(radians(60/6))*TopBevelRadius
831     y = cos(radians(60/6))*TopBevelRadius
832     vec2 = Mathutils.Vector([x,y,0.0])
833     verts.append([x,y,0.0])
834     
835     
836     x = sin(radians(60/3))*TopBevelRadius
837     y = cos(radians(60/3))*TopBevelRadius
838     vec3 = Mathutils.Vector([x,y,0.0])
839     verts.append([x,y,0.0])
840     
841     
842     x = sin(radians(60/2))*TopBevelRadius
843     y = cos(radians(60/2))*TopBevelRadius
844     vec4 = Mathutils.Vector([x,y,0.0])
845     verts.append([x,y,0.0])
846     Row += 1
847     
848     #Flats
849     
850     x = tan(radians(0))*Half_Flat
851     dvec = vec1 - Mathutils.Vector([x,Half_Flat,0.0])
852     verts.append([x,Half_Flat,-dvec.length])
853     
854     
855     x = tan(radians(60/6))*Half_Flat
856     dvec = vec2 - Mathutils.Vector([x,Half_Flat,0.0])
857     verts.append([x,Half_Flat,-dvec.length])
858     
859
860     x = tan(radians(60/3))*Half_Flat
861     dvec = vec3 - Mathutils.Vector([x,Half_Flat,0.0])
862     Lowest_Point = -dvec.length
863     verts.append([x,Half_Flat,-dvec.length])
864     
865
866     x = tan(radians(60/2))*Half_Flat
867     dvec = vec4 - Mathutils.Vector([x,Half_Flat,0.0])
868     Lowest_Point = -dvec.length
869     verts.append([x,Half_Flat,-dvec.length])
870     Row += 1
871     
872     #down Bits Tri
873     x = tan(radians(0))*Half_Flat
874     verts.append([x,Half_Flat,Lowest_Point])
875     
876     x = tan(radians(60/6))*Half_Flat
877     verts.append([x,Half_Flat,Lowest_Point])
878
879     x = tan(radians(60/3))*Half_Flat
880     verts.append([x,Half_Flat,Lowest_Point])
881     
882     x = tan(radians(60/2))*Half_Flat
883     verts.append([x,Half_Flat,Lowest_Point])
884     Row += 1
885
886     #down Bits
887     
888     x = tan(radians(0))*Half_Flat
889     verts.append([x,Half_Flat,-Flat_Height])
890     
891     x = tan(radians(60/6))*Half_Flat
892     verts.append([x,Half_Flat,-Flat_Height])
893
894     x = tan(radians(60/3))*Half_Flat
895     verts.append([x,Half_Flat,-Flat_Height])
896     
897     x = tan(radians(60/2))*Half_Flat
898     verts.append([x,Half_Flat,-Flat_Height])
899     Row += 1
900     
901     
902     #under cut 
903        
904     x = sin(radians(0))*Half_Flat
905     y = cos(radians(0))*Half_Flat
906     vec1 = Mathutils.Vector([x,y,0.0])
907     verts.append([x,y,-Flat_Height])
908     
909     x = sin(radians(60/6))*Half_Flat
910     y = cos(radians(60/6))*Half_Flat
911     vec2 = Mathutils.Vector([x,y,0.0])
912     verts.append([x,y,-Flat_Height])
913     
914     x = sin(radians(60/3))*Half_Flat
915     y = cos(radians(60/3))*Half_Flat
916     vec3 = Mathutils.Vector([x,y,0.0])
917     verts.append([x,y,-Flat_Height])
918     
919     x = sin(radians(60/2))*Half_Flat
920     y = cos(radians(60/2))*Half_Flat
921     vec3 = Mathutils.Vector([x,y,0.0])
922     verts.append([x,y,-Flat_Height])
923     Row += 1
924     
925     #under cut down bit
926     x = sin(radians(0))*Half_Flat
927     y = cos(radians(0))*Half_Flat
928     vec1 = Mathutils.Vector([x,y,0.0])
929     verts.append([x,y,-Flat_Height-Undercut_Height])
930     
931     x = sin(radians(60/6))*Half_Flat
932     y = cos(radians(60/6))*Half_Flat
933     vec2 = Mathutils.Vector([x,y,0.0])
934     verts.append([x,y,-Flat_Height-Undercut_Height])
935     
936     x = sin(radians(60/3))*Half_Flat
937     y = cos(radians(60/3))*Half_Flat
938     vec3 = Mathutils.Vector([x,y,0.0])
939     verts.append([x,y,-Flat_Height-Undercut_Height])
940     
941     x = sin(radians(60/2))*Half_Flat
942     y = cos(radians(60/2))*Half_Flat
943     vec3 = Mathutils.Vector([x,y,0.0])
944     verts.append([x,y,-Flat_Height-Undercut_Height])
945     Row += 1
946     
947     #under cut to Shank BEVEAL
948     x = sin(radians(0))*(SHANK_RADIUS+Shank_Bevel)
949     y = cos(radians(0))*(SHANK_RADIUS+Shank_Bevel)
950     vec1 = Mathutils.Vector([x,y,0.0])
951     verts.append([x,y,-Flat_Height-Undercut_Height])
952     
953     x = sin(radians(60/6))*(SHANK_RADIUS+Shank_Bevel)
954     y = cos(radians(60/6))*(SHANK_RADIUS+Shank_Bevel)
955     vec2 = Mathutils.Vector([x,y,0.0])
956     verts.append([x,y,-Flat_Height-Undercut_Height])
957     
958     x = sin(radians(60/3))*(SHANK_RADIUS+Shank_Bevel)
959     y = cos(radians(60/3))*(SHANK_RADIUS+Shank_Bevel)
960     vec3 = Mathutils.Vector([x,y,0.0])
961     verts.append([x,y,-Flat_Height-Undercut_Height])
962     
963     x = sin(radians(60/2))*(SHANK_RADIUS+Shank_Bevel)
964     y = cos(radians(60/2))*(SHANK_RADIUS+Shank_Bevel)
965     vec3 = Mathutils.Vector([x,y,0.0])
966     verts.append([x,y,-Flat_Height-Undercut_Height])
967     Row += 1
968     
969     #under cut to Shank BEVEAL
970     x = sin(radians(0))*SHANK_RADIUS
971     y = cos(radians(0))*SHANK_RADIUS
972     vec1 = Mathutils.Vector([x,y,0.0])
973     verts.append([x,y,-Flat_Height-Undercut_Height-Shank_Bevel])
974     
975     x = sin(radians(60/6))*SHANK_RADIUS
976     y = cos(radians(60/6))*SHANK_RADIUS
977     vec2 = Mathutils.Vector([x,y,0.0])
978     verts.append([x,y,-Flat_Height-Undercut_Height-Shank_Bevel])
979     
980     x = sin(radians(60/3))*SHANK_RADIUS
981     y = cos(radians(60/3))*SHANK_RADIUS
982     vec3 = Mathutils.Vector([x,y,0.0])
983     verts.append([x,y,-Flat_Height-Undercut_Height-Shank_Bevel])
984     
985     x = sin(radians(60/2))*SHANK_RADIUS
986     y = cos(radians(60/2))*SHANK_RADIUS
987     vec3 = Mathutils.Vector([x,y,0.0])
988     verts.append([x,y,-Flat_Height-Undercut_Height-Shank_Bevel])
989     Row += 1
990     
991     
992     #Global_Head_Height = 0 - (-HEIGHT-0.1)
993     faces.extend(Build_Face_List_Quads(FaceStart,3,Row - 1))
994        
995     
996     Mirror_Verts,Mirror_Faces = Mirror_Verts_Faces(verts,faces,'y')
997     verts.extend(Mirror_Verts)
998     faces.extend(Mirror_Faces)
999     
1000     Spin_Verts,Spin_Faces = SpinDup(verts,faces,360,6,'z')
1001     
1002     return Spin_Verts,Spin_Faces,0 - (-HEIGHT)
1003    
1004     
1005 ##########################################################################################
1006 ##########################################################################################
1007 ##                    Create Bolt
1008 ##########################################################################################
1009 ##########################################################################################
1010
1011
1012
1013 def MakeBolt():
1014     global Phillips_Bit_Depth 
1015     global Philips_Bit_Dia 
1016
1017     global Allen_Bit_Depth 
1018     global Allen_Bit_Flat_Distance 
1019
1020     global Hex_Head_Height 
1021     global Hex_Head_Flat_Distance 
1022
1023     global Cap_Head_Dia 
1024     global Cap_Head_Height 
1025     
1026
1027     global Dome_Head_Dia 
1028
1029     global Pan_Head_Dia 
1030
1031     global Shank_Dia 
1032     global Shank_Length 
1033
1034     global Thread_Length
1035     global Major_Dia 
1036     global Minor_Dia 
1037     global Pitch 
1038     global Crest_Percent 
1039     global Root_Percent 
1040     
1041     verts = []
1042     faces = []
1043     Bit_Verts = []
1044     Bit_Faces = []
1045     Bit_Dia = 0.001
1046     Head_Verts = []
1047     Head_Faces= []
1048     Head_Height = 0.0
1049     ReSized_Allen_Bit_Flat_Distance = Allen_Bit_Flat_Distance.val  # set default  
1050    
1051     
1052     Head_Height = Hex_Head_Height.val # will be changed by the Head Functions
1053     
1054     if Bit_Type['ALLEN'][0].val and Head_Type['PAN'][0].val:
1055         #need to size Allen bit if it is too big.
1056         if  Allen_Bit_Dia(Allen_Bit_Flat_Distance.val) > Max_Pan_Bit_Dia(Pan_Head_Dia.val):
1057             ReSized_Allen_Bit_Flat_Distance = Allen_Bit_Dia_To_Flat(Max_Pan_Bit_Dia(Pan_Head_Dia.val)) * 1.05
1058             print "Resized Allen Bit Flat Distance to ",ReSized_Allen_Bit_Flat_Distance 
1059  
1060     #bit Mesh
1061     if Bit_Type['ALLEN'][0].val:
1062         Bit_Verts,Bit_Faces,Bit_Dia = Create_Allen_Bit(ReSized_Allen_Bit_Flat_Distance,Allen_Bit_Depth.val)
1063     
1064     if Bit_Type['PHILLIPS'][0].val:
1065         Bit_Verts,Bit_Faces,Bit_Dia = Create_Phillips_Bit(Philips_Bit_Dia.val,Philips_Bit_Dia.val*(0.5/1.82),Phillips_Bit_Depth.val)
1066    
1067         
1068     #Head Mesh
1069     if Head_Type['HEX'][0].val:  
1070         Head_Verts,Head_Faces,Head_Height = Create_Hex_Head(Hex_Head_Flat_Distance.val,Bit_Dia,Shank_Dia.val,Hex_Head_Height.val)
1071
1072     elif Head_Type['CAP'][0].val:  
1073         Head_Verts,Head_Faces,Head_Height = Create_Cap_Head(Bit_Dia,Cap_Head_Dia.val,Shank_Dia.val,Cap_Head_Height.val,Cap_Head_Dia.val*(1.0/19.0),Cap_Head_Dia.val*(1.0/19.0))
1074         
1075     elif Head_Type['DOME'][0].val:  
1076         Head_Verts,Head_Faces,Head_Height = Create_Dome_Head(Bit_Dia,Dome_Head_Dia.val,Shank_Dia.val,Hex_Head_Height.val,1,1,0)
1077     
1078     elif Head_Type['PAN'][0].val:  
1079         Head_Verts,Head_Faces,Head_Height = Create_Pan_Head(Bit_Dia,Pan_Head_Dia.val,Shank_Dia.val,Hex_Head_Height.val,1,1,0)
1080
1081
1082     Face_Start = len(verts)
1083     verts.extend(Move_Verts_Up_Z(Bit_Verts,Head_Height))
1084     faces.extend(Copy_Faces(Bit_Faces,Face_Start))
1085
1086     Face_Start = len(verts)
1087     verts.extend(Move_Verts_Up_Z(Head_Verts,Head_Height))
1088     faces.extend(Copy_Faces(Head_Faces,Face_Start))
1089
1090     Face_Start = len(verts)
1091     Thread_Verts,Thread_Faces,Thread_Height = Create_External_Thread(Shank_Dia.val,Shank_Length.val,Minor_Dia.val,Major_Dia.val,Pitch.val,Thread_Length.val,Crest_Percent.val,Root_Percent.val)
1092
1093     verts.extend(Move_Verts_Up_Z(Thread_Verts,00))
1094     faces.extend(Copy_Faces(Thread_Faces,Face_Start))
1095     
1096     return Move_Verts_Up_Z(verts,Thread_Height),faces
1097
1098
1099
1100
1101
1102
1103
1104 ##########################################################################################
1105 ##########################################################################################
1106 ##                    Create Internal Thread
1107 ##########################################################################################
1108 ##########################################################################################
1109
1110
1111 def Create_Internal_Thread_Start_Verts(verts,INNER_RADIUS,OUTTER_RADIUS,PITCH,DIV,CREST_PERCENT,ROOT_PERCENT,Height_Offset):
1112     
1113     
1114     Ret_Row = 0;
1115     
1116     Height_Offset = Height_Offset + PITCH  #Move the offset up so that the verts start at 
1117                                            #at the correct place  (Height_Start)
1118     
1119     Half_Pitch = float(PITCH)/2
1120     Height_Start = Height_Offset - PITCH 
1121     Height_Step = float(PITCH)/float(DIV)
1122     Deg_Step = 360.0 /float(DIV)
1123     
1124     Crest_Height = float(PITCH) * float(CREST_PERCENT)/float(100)
1125     Root_Height = float(PITCH) * float(ROOT_PERCENT)/float(100)
1126     Root_to_Crest_Height = Crest_to_Root_Height = (float(PITCH) - (Crest_Height + Root_Height))/2.0
1127     
1128
1129     Rank = float(OUTTER_RADIUS - INNER_RADIUS)/float(DIV)
1130     for j in range(1):
1131         
1132         for i in range(DIV+1):
1133             z = Height_Offset - (Height_Step*i) 
1134             if z > Height_Start:
1135                 z = Height_Start
1136             x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
1137             y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
1138             verts.append([x,y,z])
1139         Height_Offset -= Crest_Height
1140         Ret_Row += 1
1141     
1142         for i in range(DIV+1):
1143             z = Height_Offset - (Height_Step*i) 
1144             if z > Height_Start:
1145                 z = Height_Start
1146             
1147             x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
1148             y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
1149             verts.append([x,y,z ])
1150         Height_Offset -= Crest_to_Root_Height
1151         Ret_Row += 1
1152     
1153         
1154         for i in range(DIV+1):
1155             z = Height_Offset - (Height_Step*i) 
1156             if z > Height_Start:
1157                 z = Height_Start
1158             
1159             x = sin(radians(i*Deg_Step))*INNER_RADIUS
1160             y = cos(radians(i*Deg_Step))*INNER_RADIUS
1161             if j == 0:
1162                 x = sin(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank))
1163                 y = cos(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank))
1164             verts.append([x,y,z ])
1165         Height_Offset -= Root_Height
1166         Ret_Row += 1
1167     
1168         for i in range(DIV+1):
1169             z = Height_Offset - (Height_Step*i) 
1170             if z > Height_Start:
1171                 z = Height_Start
1172             
1173             x = sin(radians(i*Deg_Step))*INNER_RADIUS
1174             y = cos(radians(i*Deg_Step))*INNER_RADIUS
1175
1176             if j == 0:
1177                 x = sin(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank))
1178                 y = cos(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank))
1179             verts.append([x,y,z ])
1180         Height_Offset -= Root_to_Crest_Height
1181         Ret_Row += 1
1182    
1183     return Ret_Row,Height_Offset
1184
1185
1186 def Create_Internal_Thread_End_Verts(verts,INNER_RADIUS,OUTTER_RADIUS,PITCH,DIV,CREST_PERCENT,ROOT_PERCENT,Height_Offset):
1187     
1188     
1189     Ret_Row = 0;
1190     
1191     Half_Pitch = float(PITCH)/2
1192     #Height_End = Height_Offset - PITCH - PITCH - PITCH- PITCH - PITCH- PITCH
1193     Height_End = Height_Offset - PITCH 
1194     #Height_End = -2.1
1195     Height_Step = float(PITCH)/float(DIV)
1196     Deg_Step = 360.0 /float(DIV)
1197     
1198     Crest_Height = float(PITCH) * float(CREST_PERCENT)/float(100)
1199     Root_Height = float(PITCH) * float(ROOT_PERCENT)/float(100)
1200     Root_to_Crest_Height = Crest_to_Root_Height = (float(PITCH) - (Crest_Height + Root_Height))/2.0
1201    
1202     
1203
1204     Rank = float(OUTTER_RADIUS - INNER_RADIUS)/float(DIV)
1205     
1206     Num = 0
1207     
1208     for j in range(2):
1209         
1210         for i in range(DIV+1):
1211             z = Height_Offset - (Height_Step*i) 
1212             if z < Height_End:
1213                 z = Height_End
1214             x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
1215             y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
1216             verts.append([x,y,z])
1217         Height_Offset -= Crest_Height
1218         Ret_Row += 1
1219     
1220     
1221         for i in range(DIV+1):
1222             z = Height_Offset - (Height_Step*i) 
1223             if z < Height_End:
1224                 z = Height_End
1225             
1226             x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
1227             y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
1228             verts.append([x,y,z ])
1229         Height_Offset -= Crest_to_Root_Height
1230         Ret_Row += 1
1231     
1232     
1233         for i in range(DIV+1):
1234             z = Height_Offset - (Height_Step*i) 
1235             if z < Height_End:
1236                 z = Height_End
1237             
1238             x = sin(radians(i*Deg_Step))*INNER_RADIUS
1239             y = cos(radians(i*Deg_Step))*INNER_RADIUS
1240             if j == Num:
1241                 x = sin(radians(i*Deg_Step))*(INNER_RADIUS + (i*Rank))
1242                 y = cos(radians(i*Deg_Step))*(INNER_RADIUS + (i*Rank))
1243             if j > Num:
1244                 x = sin(radians(i*Deg_Step))*(OUTTER_RADIUS)
1245                 y = cos(radians(i*Deg_Step))*(OUTTER_RADIUS )
1246                 
1247             verts.append([x,y,z ])
1248         Height_Offset -= Root_Height
1249         Ret_Row += 1
1250     
1251     
1252         for i in range(DIV+1):
1253             z = Height_Offset - (Height_Step*i) 
1254             if z < Height_End:
1255                 z = Height_End
1256             
1257             x = sin(radians(i*Deg_Step))*INNER_RADIUS
1258             y = cos(radians(i*Deg_Step))*INNER_RADIUS
1259
1260             if j == Num:
1261                 x = sin(radians(i*Deg_Step))*(INNER_RADIUS + (i*Rank))
1262                 y = cos(radians(i*Deg_Step))*(INNER_RADIUS + (i*Rank))
1263             if j > Num:
1264                 x = sin(radians(i*Deg_Step))*(OUTTER_RADIUS )
1265                 y = cos(radians(i*Deg_Step))*(OUTTER_RADIUS )
1266                 
1267             verts.append([x,y,z ])
1268         Height_Offset -= Root_to_Crest_Height
1269         Ret_Row += 1
1270
1271        
1272     return Ret_Row,Height_End  # send back Height End as this is the lowest point
1273
1274
1275 def Create_Internal_Thread(INNER_DIA,OUTTER_DIA,PITCH,HEIGHT,CREST_PERCENT,ROOT_PERCENT,INTERNAL = 1):
1276     verts = []
1277     faces = []
1278     
1279     DIV = 36
1280     
1281     INNER_RADIUS = INNER_DIA/2
1282     OUTTER_RADIUS = OUTTER_DIA/2
1283     
1284     Half_Pitch = float(PITCH)/2
1285     Deg_Step = 360.0 /float(DIV)
1286     Height_Step = float(PITCH)/float(DIV)
1287             
1288     Num = int(round((HEIGHT- PITCH)/PITCH))  # less one pitch for the start and end that is 1/2 pitch high    
1289     
1290     Col = 0
1291     Row = 0
1292     
1293     
1294     Crest_Height = float(PITCH) * float(CREST_PERCENT)/float(100)
1295     Root_Height = float(PITCH) * float(ROOT_PERCENT)/float(100)
1296     Root_to_Crest_Height = Crest_to_Root_Height = (float(PITCH) - (Crest_Height + Root_Height))/2.0
1297     
1298     Height_Offset = 0
1299     FaceStart = len(verts)
1300     
1301     Row_Inc,Height_Offset = Create_Internal_Thread_Start_Verts(verts,INNER_RADIUS,OUTTER_RADIUS,PITCH,DIV,CREST_PERCENT,ROOT_PERCENT,Height_Offset)
1302     Row += Row_Inc
1303     
1304     for j in range(Num):
1305         
1306         for i in range(DIV+1):
1307             x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
1308             y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
1309             verts.append([x,y,Height_Offset - (Height_Step*i) ])
1310         Height_Offset -= Crest_Height
1311         Row += 1
1312     
1313         for i in range(DIV+1):
1314             x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
1315             y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
1316             verts.append([x,y,Height_Offset - (Height_Step*i) ])
1317         Height_Offset -= Crest_to_Root_Height
1318         Row += 1
1319     
1320         
1321         for i in range(DIV+1):
1322             x = sin(radians(i*Deg_Step))*INNER_RADIUS
1323             y = cos(radians(i*Deg_Step))*INNER_RADIUS
1324             verts.append([x,y,Height_Offset - (Height_Step*i) ])
1325         Height_Offset -= Root_Height
1326         Row += 1
1327     
1328         for i in range(DIV+1):
1329             x = sin(radians(i*Deg_Step))*INNER_RADIUS
1330             y = cos(radians(i*Deg_Step))*INNER_RADIUS
1331             verts.append([x,y,Height_Offset - (Height_Step*i) ])
1332         Height_Offset -= Root_to_Crest_Height
1333         Row += 1
1334     
1335
1336     Row_Inc,Height_Offset = Create_Internal_Thread_End_Verts(verts,INNER_RADIUS,OUTTER_RADIUS,PITCH,DIV,CREST_PERCENT,ROOT_PERCENT,Height_Offset)
1337     Row += Row_Inc
1338     
1339     faces.extend(Build_Face_List_Quads(FaceStart,DIV,Row -1,INTERNAL))
1340     
1341     return verts,faces,0 - Height_Offset
1342
1343
1344
1345 ##########################################################################################
1346 ##########################################################################################
1347 ##                    Create External Thread
1348 ##########################################################################################
1349 ##########################################################################################
1350
1351
1352
1353 def Thread_Start3(verts,INNER_RADIUS,OUTTER_RADIUS,PITCH,DIV,CREST_PERCENT,ROOT_PERCENT,Height_Offset):
1354     
1355     
1356     Ret_Row = 0;
1357     
1358     Half_Pitch = float(PITCH)/2
1359     Height_Start = Height_Offset - PITCH
1360     Height_Step = float(PITCH)/float(DIV)
1361     Deg_Step = 360.0 /float(DIV)
1362     
1363     Crest_Height = float(PITCH) * float(CREST_PERCENT)/float(100)
1364     Root_Height = float(PITCH) * float(ROOT_PERCENT)/float(100)
1365     Root_to_Crest_Height = Crest_to_Root_Height = (float(PITCH) - (Crest_Height + Root_Height))/2.0
1366    
1367 #theard start
1368
1369     Rank = float(OUTTER_RADIUS - INNER_RADIUS)/float(DIV)
1370     for j in range(4):
1371         
1372         for i in range(DIV+1):
1373             z = Height_Offset - (Height_Step*i) 
1374             if z > Height_Start:
1375                 z = Height_Start
1376             x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
1377             y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
1378             verts.append([x,y,z])
1379         Height_Offset -= Crest_Height
1380         Ret_Row += 1
1381     
1382         for i in range(DIV+1):
1383             z = Height_Offset - (Height_Step*i) 
1384             if z > Height_Start:
1385                 z = Height_Start
1386             
1387             x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
1388             y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
1389             verts.append([x,y,z ])
1390         Height_Offset -= Crest_to_Root_Height
1391         Ret_Row += 1
1392     
1393         
1394         for i in range(DIV+1):
1395             z = Height_Offset - (Height_Step*i) 
1396             if z > Height_Start:
1397                 z = Height_Start
1398             
1399             x = sin(radians(i*Deg_Step))*INNER_RADIUS
1400             y = cos(radians(i*Deg_Step))*INNER_RADIUS
1401             if j == 0:
1402                 x = sin(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank))
1403                 y = cos(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank))
1404             verts.append([x,y,z ])
1405         Height_Offset -= Root_Height
1406         Ret_Row += 1
1407     
1408         for i in range(DIV+1):
1409             z = Height_Offset - (Height_Step*i) 
1410             if z > Height_Start:
1411                 z = Height_Start
1412             
1413             x = sin(radians(i*Deg_Step))*INNER_RADIUS
1414             y = cos(radians(i*Deg_Step))*INNER_RADIUS
1415
1416             if j == 0:
1417                 x = sin(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank))
1418                 y = cos(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank))
1419             verts.append([x,y,z ])
1420         Height_Offset -= Root_to_Crest_Height
1421         Ret_Row += 1
1422    
1423     return Ret_Row,Height_Offset
1424
1425
1426 def Create_Shank_Verts(START_DIA,OUTTER_DIA,LENGTH,Z_LOCATION = 0):
1427
1428     verts = []
1429     DIV = 36
1430     
1431     START_RADIUS = START_DIA/2
1432     OUTTER_RADIUS = OUTTER_DIA/2
1433     
1434     Opp = abs(START_RADIUS - OUTTER_RADIUS)
1435     Taper_Lentgh = Opp/tan(radians(31));
1436     
1437     if Taper_Lentgh > LENGTH:
1438         Taper_Lentgh = 0
1439     
1440     Stright_Length = LENGTH - Taper_Lentgh
1441     
1442     Deg_Step = 360.0 /float(DIV)
1443     
1444     Row = 0
1445     
1446     Lowest_Z_Vert = 0;    
1447     
1448     Height_Offset = Z_LOCATION
1449
1450
1451         #ring
1452     for i in range(DIV+1): 
1453         x = sin(radians(i*Deg_Step))*START_RADIUS
1454         y = cos(radians(i*Deg_Step))*START_RADIUS
1455         z =  Height_Offset - 0
1456         verts.append([x,y,z])
1457         Lowest_Z_Vert = min(Lowest_Z_Vert,z)
1458     Height_Offset -= Stright_Length
1459     Row += 1
1460
1461     for i in range(DIV+1): 
1462         x = sin(radians(i*Deg_Step))*START_RADIUS
1463         y = cos(radians(i*Deg_Step))*START_RADIUS
1464         z =  Height_Offset - 0
1465         verts.append([x,y,z])
1466         Lowest_Z_Vert = min(Lowest_Z_Vert,z)
1467     Height_Offset -= Taper_Lentgh
1468     Row += 1
1469
1470
1471     return verts,Row,Height_Offset
1472
1473
1474 def Create_Thread_Start_Verts(INNER_DIA,OUTTER_DIA,PITCH,CREST_PERCENT,ROOT_PERCENT,Z_LOCATION = 0):
1475     
1476     verts = []
1477     DIV = 36
1478     
1479     INNER_RADIUS = INNER_DIA/2
1480     OUTTER_RADIUS = OUTTER_DIA/2
1481     
1482     Half_Pitch = float(PITCH)/2
1483     Deg_Step = 360.0 /float(DIV)
1484     Height_Step = float(PITCH)/float(DIV)
1485
1486     Row = 0
1487     
1488     Lowest_Z_Vert = 0;    
1489     
1490     Height_Offset = Z_LOCATION
1491         
1492     Height_Start = Height_Offset 
1493     
1494     Crest_Height = float(PITCH) * float(CREST_PERCENT)/float(100)
1495     Root_Height = float(PITCH) * float(ROOT_PERCENT)/float(100)
1496     Root_to_Crest_Height = Crest_to_Root_Height = (float(PITCH) - (Crest_Height + Root_Height))/2.0
1497
1498     Rank = float(OUTTER_RADIUS - INNER_RADIUS)/float(DIV)
1499     
1500     Height_Offset = Z_LOCATION + PITCH 
1501     Cut_off = Z_LOCATION
1502   
1503     
1504     for j in range(1):
1505         
1506         for i in range(DIV+1):
1507             x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
1508             y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
1509             z = Height_Offset - (Height_Step*i)
1510             if z > Cut_off : z = Cut_off
1511             verts.append([x,y,z])
1512             Lowest_Z_Vert = min(Lowest_Z_Vert,z)
1513         Height_Offset -= Crest_Height
1514         Row += 1
1515     
1516         for i in range(DIV+1):
1517             x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
1518             y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
1519             z = Height_Offset - (Height_Step*i)
1520             if z > Cut_off : z = Cut_off
1521             verts.append([x,y,z])
1522             Lowest_Z_Vert = min(Lowest_Z_Vert,z)
1523         Height_Offset -= Crest_to_Root_Height
1524         Row += 1
1525         
1526         for i in range(DIV+1):
1527             x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
1528             y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
1529             z = Height_Offset - (Height_Step*i)
1530             if z > Cut_off : z = Cut_off 
1531             verts.append([x,y,z])
1532             Lowest_Z_Vert = min(Lowest_Z_Vert,z)
1533         Height_Offset -= Root_Height
1534         Row += 1
1535     
1536         for i in range(DIV+1):
1537             x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
1538             y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
1539             z = Height_Offset - (Height_Step*i)
1540             if z > Cut_off : z = Cut_off 
1541             verts.append([x,y,z])
1542             Lowest_Z_Vert = min(Lowest_Z_Vert,z)
1543         Height_Offset -= Root_to_Crest_Height
1544         Row += 1
1545     
1546     
1547     for j in range(2):
1548         for i in range(DIV+1):
1549             z = Height_Offset - (Height_Step*i) 
1550             if z > Height_Start:
1551                 z = Height_Start
1552             x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
1553             y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
1554             verts.append([x,y,z])
1555             Lowest_Z_Vert = min(Lowest_Z_Vert,z)
1556         Height_Offset -= Crest_Height
1557         Row += 1
1558     
1559         for i in range(DIV+1):
1560             z = Height_Offset - (Height_Step*i) 
1561             if z > Height_Start:
1562                 z = Height_Start
1563             
1564             x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
1565             y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
1566             verts.append([x,y,z ])
1567             Lowest_Z_Vert = min(Lowest_Z_Vert,z)
1568         Height_Offset -= Crest_to_Root_Height
1569         Row += 1
1570     
1571         
1572         for i in range(DIV+1):
1573             z = Height_Offset - (Height_Step*i) 
1574             if z > Height_Start:
1575                 z = Height_Start
1576             
1577             x = sin(radians(i*Deg_Step))*INNER_RADIUS
1578             y = cos(radians(i*Deg_Step))*INNER_RADIUS
1579             if j == 0:
1580                 x = sin(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank))
1581                 y = cos(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank))
1582             verts.append([x,y,z ])
1583             Lowest_Z_Vert = min(Lowest_Z_Vert,z)
1584         Height_Offset -= Root_Height
1585         Row += 1
1586     
1587         for i in range(DIV+1):
1588             z = Height_Offset - (Height_Step*i) 
1589             if z > Height_Start:
1590                 z = Height_Start
1591             
1592             x = sin(radians(i*Deg_Step))*INNER_RADIUS
1593             y = cos(radians(i*Deg_Step))*INNER_RADIUS
1594
1595             if j == 0:
1596                 x = sin(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank))
1597                 y = cos(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank))
1598             verts.append([x,y,z ])
1599             Lowest_Z_Vert = min(Lowest_Z_Vert,z)
1600         Height_Offset -= Root_to_Crest_Height
1601         Row += 1
1602         
1603    
1604     return verts,Row,Height_Offset
1605
1606
1607
1608 def Create_Thread_Verts(INNER_DIA,OUTTER_DIA,PITCH,HEIGHT,CREST_PERCENT,ROOT_PERCENT,Z_LOCATION = 0):
1609     verts = []
1610         
1611     DIV = 36
1612     
1613     INNER_RADIUS = INNER_DIA/2
1614     OUTTER_RADIUS = OUTTER_DIA/2
1615     
1616     Half_Pitch = float(PITCH)/2
1617     Deg_Step = 360.0 /float(DIV)
1618     Height_Step = float(PITCH)/float(DIV)
1619
1620     NUM_OF_START_THREADS = 4.0
1621     NUM_OF_END_THREADS = 3.0
1622     Num = int((HEIGHT- ((NUM_OF_START_THREADS*PITCH) + (NUM_OF_END_THREADS*PITCH) ))/PITCH)
1623     Row = 0
1624     
1625
1626     Crest_Height = float(PITCH) * float(CREST_PERCENT)/float(100)
1627     Root_Height = float(PITCH) * float(ROOT_PERCENT)/float(100)
1628     Root_to_Crest_Height = Crest_to_Root_Height = (float(PITCH) - (Crest_Height + Root_Height))/2.0
1629
1630
1631     Height_Offset = Z_LOCATION
1632     
1633     Lowest_Z_Vert = 0;
1634     FaceStart = len(verts)
1635     
1636     
1637     for j in range(Num):
1638         
1639         for i in range(DIV+1):
1640             x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
1641             y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
1642             z = Height_Offset - (Height_Step*i) 
1643             verts.append([x,y,z])
1644             Lowest_Z_Vert = min(Lowest_Z_Vert,z)
1645         Height_Offset -= Crest_Height
1646         Row += 1
1647     
1648         for i in range(DIV+1):
1649             x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
1650             y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
1651             z = Height_Offset - (Height_Step*i)
1652             verts.append([x,y,z])
1653             Lowest_Z_Vert = min(Lowest_Z_Vert,z)
1654         Height_Offset -= Crest_to_Root_Height
1655         Row += 1
1656     
1657         
1658         for i in range(DIV+1):
1659             x = sin(radians(i*Deg_Step))*INNER_RADIUS
1660             y = cos(radians(i*Deg_Step))*INNER_RADIUS
1661             z = Height_Offset - (Height_Step*i) 
1662             verts.append([x,y,z])
1663             Lowest_Z_Vert = min(Lowest_Z_Vert,z)
1664         Height_Offset -= Root_Height
1665         Row += 1
1666     
1667         for i in range(DIV+1):
1668             x = sin(radians(i*Deg_Step))*INNER_RADIUS
1669             y = cos(radians(i*Deg_Step))*INNER_RADIUS
1670             z = Height_Offset - (Height_Step*i) 
1671             verts.append([x,y,z])
1672             Lowest_Z_Vert = min(Lowest_Z_Vert,z)
1673         Height_Offset -= Root_to_Crest_Height
1674         Row += 1
1675     
1676     return verts,Row,Height_Offset
1677
1678
1679
1680 def Create_Thread_End_Verts(INNER_DIA,OUTTER_DIA,PITCH,CREST_PERCENT,ROOT_PERCENT,Z_LOCATION = 0):
1681     verts = []
1682         
1683     DIV = 36
1684
1685     INNER_RADIUS = INNER_DIA/2
1686     OUTTER_RADIUS = OUTTER_DIA/2
1687     
1688     Half_Pitch = float(PITCH)/2
1689     Deg_Step = 360.0 /float(DIV)
1690     Height_Step = float(PITCH)/float(DIV)
1691
1692     Crest_Height = float(PITCH) * float(CREST_PERCENT)/float(100)
1693     Root_Height = float(PITCH) * float(ROOT_PERCENT)/float(100)
1694     Root_to_Crest_Height = Crest_to_Root_Height = (float(PITCH) - (Crest_Height + Root_Height))/2.0
1695        
1696     Col = 0
1697     Row = 0
1698     
1699     Height_Offset = Z_LOCATION 
1700     
1701     Tapper_Height_Start = Height_Offset - PITCH - PITCH 
1702     
1703     Max_Height = Tapper_Height_Start - PITCH 
1704     
1705     Lowest_Z_Vert = 0;
1706     
1707     FaceStart = len(verts)
1708     for j in range(4):
1709         
1710         for i in range(DIV+1):
1711             z = Height_Offset - (Height_Step*i)
1712             z = max(z,Max_Height)
1713             Tapper_Radius = OUTTER_RADIUS
1714             if z < Tapper_Height_Start:
1715                 Tapper_Radius = OUTTER_RADIUS - (Tapper_Height_Start - z)
1716
1717             x = sin(radians(i*Deg_Step))*(Tapper_Radius)
1718             y = cos(radians(i*Deg_Step))*(Tapper_Radius)
1719             verts.append([x,y,z])
1720             Lowest_Z_Vert = min(Lowest_Z_Vert,z)
1721         Height_Offset -= Crest_Height
1722         Row += 1
1723     
1724         for i in range(DIV+1):
1725             z = Height_Offset - (Height_Step*i)
1726             z = max(z,Max_Height)
1727             Tapper_Radius = OUTTER_RADIUS
1728             if z < Tapper_Height_Start:
1729                 Tapper_Radius = OUTTER_RADIUS - (Tapper_Height_Start - z)
1730
1731             x = sin(radians(i*Deg_Step))*(Tapper_Radius)
1732             y = cos(radians(i*Deg_Step))*(Tapper_Radius)
1733             verts.append([x,y,z])
1734             Lowest_Z_Vert = min(Lowest_Z_Vert,z)
1735         Height_Offset -= Crest_to_Root_Height
1736         Row += 1
1737     
1738         
1739         for i in range(DIV+1):
1740             z = Height_Offset - (Height_Step*i)
1741             z = max(z,Max_Height)
1742             Tapper_Radius = OUTTER_RADIUS - (Tapper_Height_Start - z)
1743             if Tapper_Radius > INNER_RADIUS:
1744                Tapper_Radius = INNER_RADIUS
1745             
1746             x = sin(radians(i*Deg_Step))*(Tapper_Radius)
1747             y = cos(radians(i*Deg_Step))*(Tapper_Radius)
1748             verts.append([x,y,z])
1749             Lowest_Z_Vert = min(Lowest_Z_Vert,z)
1750         Height_Offset -= Root_Height
1751         Row += 1
1752     
1753         for i in range(DIV+1):
1754             z = Height_Offset - (Height_Step*i)
1755             z = max(z,Max_Height)
1756             Tapper_Radius = OUTTER_RADIUS - (Tapper_Height_Start - z)
1757             if Tapper_Radius > INNER_RADIUS:
1758                Tapper_Radius = INNER_RADIUS
1759             
1760             x = sin(radians(i*Deg_Step))*(Tapper_Radius)
1761             y = cos(radians(i*Deg_Step))*(Tapper_Radius)
1762             verts.append([x,y,z])
1763             Lowest_Z_Vert = min(Lowest_Z_Vert,z)
1764         Height_Offset -= Root_to_Crest_Height
1765         Row += 1
1766     
1767     return verts,Row,Height_Offset,Lowest_Z_Vert
1768
1769
1770
1771
1772 def Create_External_Thread(SHANK_DIA,SHANK_LENGTH,INNER_DIA,OUTTER_DIA,PITCH,LENGTH,CREST_PERCENT,ROOT_PERCENT):
1773     
1774     verts = []
1775     faces = []
1776
1777     DIV = 36
1778     
1779     Total_Row = 0
1780     Thread_Len = 0;
1781     
1782     Face_Start = len(verts)
1783     Offset = 0.0;
1784     
1785                                              
1786     Shank_Verts,Shank_Row,Offset = Create_Shank_Verts(SHANK_DIA,OUTTER_DIA,SHANK_LENGTH,Offset)
1787     Total_Row += Shank_Row
1788
1789     Thread_Start_Verts,Thread_Start_Row,Offset = Create_Thread_Start_Verts(INNER_DIA,OUTTER_DIA,PITCH,CREST_PERCENT,ROOT_PERCENT,Offset)
1790     Total_Row += Thread_Start_Row
1791     
1792     
1793     Thread_Verts,Thread_Row,Offset = Create_Thread_Verts(INNER_DIA,OUTTER_DIA,PITCH,LENGTH,CREST_PERCENT,ROOT_PERCENT,Offset)
1794     Total_Row += Thread_Row
1795     
1796     
1797     Thread_End_Verts,Thread_End_Row,Offset,Lowest_Z_Vert = Create_Thread_End_Verts(INNER_DIA,OUTTER_DIA,PITCH,CREST_PERCENT,ROOT_PERCENT,Offset )
1798     Total_Row += Thread_End_Row       
1799     
1800     
1801     verts.extend(Shank_Verts)
1802     verts.extend(Thread_Start_Verts)
1803     verts.extend(Thread_Verts)
1804     verts.extend(Thread_End_Verts)
1805     
1806     faces.extend(Build_Face_List_Quads(Face_Start,DIV,Total_Row -1,0))
1807     faces.extend(Fill_Ring_Face(len(verts)-DIV,DIV,1))
1808     
1809     return verts,faces,0.0 - Lowest_Z_Vert
1810  
1811
1812 ##########################################################################################
1813 ##########################################################################################
1814 ##                    Create Nut
1815 ##########################################################################################
1816 ##########################################################################################
1817
1818
1819 def add_Hex_Nut(FLAT,HOLE_DIA,HEIGHT):
1820     global Global_Head_Height
1821     global Global_NutRad
1822     
1823     verts = []
1824     faces = []
1825     HOLE_RADIUS = HOLE_DIA * 0.5
1826     Half_Flat = FLAT/2
1827     Half_Height = HEIGHT/2
1828     TopBevelRadius = Half_Flat - 0.05
1829     
1830     Global_NutRad =  TopBevelRadius
1831     
1832     Row = 0;
1833     Lowest_Z_Vert = 0.0;
1834
1835     verts.append([0.0,0.0,0.0])
1836     
1837     
1838     FaceStart = len(verts)
1839     #inner hole
1840     
1841     x = sin(radians(0))*HOLE_RADIUS
1842     y = cos(radians(0))*HOLE_RADIUS
1843     verts.append([x,y,0.0])
1844     
1845     
1846     x = sin(radians(60/6))*HOLE_RADIUS
1847     y = cos(radians(60/6))*HOLE_RADIUS
1848     verts.append([x,y,0.0])
1849     
1850     
1851     x = sin(radians(60/3))*HOLE_RADIUS
1852     y = cos(radians(60/3))*HOLE_RADIUS
1853     verts.append([x,y,0.0])
1854     
1855     
1856     x = sin(radians(60/2))*HOLE_RADIUS
1857     y = cos(radians(60/2))*HOLE_RADIUS
1858     verts.append([x,y,0.0])
1859     Row += 1
1860     
1861     #bevel
1862     
1863     x = sin(radians(0))*TopBevelRadius
1864     y = cos(radians(0))*TopBevelRadius
1865     vec1 = Mathutils.Vector([x,y,0.0])
1866     verts.append([x,y,0.0])
1867     
1868     
1869     x = sin(radians(60/6))*TopBevelRadius
1870     y = cos(radians(60/6))*TopBevelRadius
1871     vec2 = Mathutils.Vector([x,y,0.0])
1872     verts.append([x,y,0.0])
1873     
1874     
1875     x = sin(radians(60/3))*TopBevelRadius
1876     y = cos(radians(60/3))*TopBevelRadius
1877     vec3 = Mathutils.Vector([x,y,0.0])
1878     verts.append([x,y,0.0])
1879     
1880     
1881     x = sin(radians(60/2))*TopBevelRadius
1882     y = cos(radians(60/2))*TopBevelRadius
1883     vec4 = Mathutils.Vector([x,y,0.0])
1884     verts.append([x,y,0.0])
1885     Row += 1
1886     
1887     #Flats
1888     
1889     x = tan(radians(0))*Half_Flat
1890     dvec = vec1 - Mathutils.Vector([x,Half_Flat,0.0])
1891     verts.append([x,Half_Flat,-dvec.length])
1892     Lowest_Z_Vert = min(Lowest_Z_Vert,-dvec.length)
1893     
1894     
1895     x = tan(radians(60/6))*Half_Flat
1896     dvec = vec2 - Mathutils.Vector([x,Half_Flat,0.0])
1897     verts.append([x,Half_Flat,-dvec.length])
1898     Lowest_Z_Vert = min(Lowest_Z_Vert,-dvec.length)
1899     
1900
1901     x = tan(radians(60/3))*Half_Flat
1902     dvec = vec3 - Mathutils.Vector([x,Half_Flat,0.0])
1903     Lowest_Point = -dvec.length
1904     verts.append([x,Half_Flat,-dvec.length])
1905     Lowest_Z_Vert = min(Lowest_Z_Vert,-dvec.length)
1906
1907     x = tan(radians(60/2))*Half_Flat
1908     dvec = vec4 - Mathutils.Vector([x,Half_Flat,0.0])
1909     Lowest_Point = -dvec.length
1910     verts.append([x,Half_Flat,-dvec.length])
1911     Lowest_Z_Vert = min(Lowest_Z_Vert,-dvec.length)
1912     Row += 1
1913     
1914     #down Bits Tri
1915     x = tan(radians(0))*Half_Flat
1916     verts.append([x,Half_Flat,Lowest_Point])
1917     
1918     
1919     x = tan(radians(60/6))*Half_Flat
1920     verts.append([x,Half_Flat,Lowest_Point])
1921
1922     x = tan(radians(60/3))*Half_Flat
1923     verts.append([x,Half_Flat,Lowest_Point])
1924     
1925     x = tan(radians(60/2))*Half_Flat
1926     verts.append([x,Half_Flat,Lowest_Point])
1927     Lowest_Z_Vert = min(Lowest_Z_Vert,Lowest_Point)
1928     Row += 1
1929
1930     #down Bits
1931     
1932     x = tan(radians(0))*Half_Flat
1933     verts.append([x,Half_Flat,-Half_Height])
1934     
1935     x = tan(radians(60/6))*Half_Flat
1936     verts.append([x,Half_Flat,-Half_Height])
1937
1938     x = tan(radians(60/3))*Half_Flat
1939     verts.append([x,Half_Flat,-Half_Height])
1940     
1941     x = tan(radians(60/2))*Half_Flat
1942     verts.append([x,Half_Flat,-Half_Height])
1943     Lowest_Z_Vert = min(Lowest_Z_Vert,-Half_Height)
1944     Row += 1
1945
1946     
1947     
1948     
1949     faces.extend(Build_Face_List_Quads(FaceStart,3,Row - 1))
1950
1951
1952     Global_Head_Height = HEIGHT
1953     
1954     Tvert,tface = Mirror_Verts_Faces(verts,faces,'z',Lowest_Z_Vert)
1955     verts.extend(Tvert)
1956     faces.extend(tface)
1957            
1958     
1959     Tvert,tface = Mirror_Verts_Faces(verts,faces,'y')
1960     verts.extend(Tvert)
1961     faces.extend(tface)
1962     
1963     S_verts,S_faces = SpinDup(verts,faces,360,6,'z')
1964     return S_verts,S_faces,TopBevelRadius
1965
1966
1967 def add_Nylon_Head(OUTSIDE_RADIUS,Z_LOCATION = 0):
1968     DIV = 36
1969     verts = []
1970     faces = []
1971     Row = 0
1972
1973     INNER_HOLE = OUTSIDE_RADIUS - (OUTSIDE_RADIUS * (1.25/4.75))
1974     EDGE_THICKNESS = (OUTSIDE_RADIUS * (0.4/4.75))
1975     RAD1 = (OUTSIDE_RADIUS * (0.5/4.75))
1976     OVER_ALL_HEIGTH = (OUTSIDE_RADIUS * (2.0/4.75))
1977     
1978     
1979     FaceStart = len(verts)
1980
1981     Start_Height = 0 - 3
1982     Height_Offset = Z_LOCATION
1983     Lowest_Z_Vert = 0
1984     
1985     x = INNER_HOLE
1986     z = (Height_Offset - OVER_ALL_HEIGTH) + EDGE_THICKNESS
1987     verts.append([x,0.0,z])
1988     Lowest_Z_Vert = min(Lowest_Z_Vert,z)
1989     Row += 1
1990     
1991     x = INNER_HOLE
1992     z = (Height_Offset - OVER_ALL_HEIGTH)
1993     verts.append([x,0.0,z])
1994     Lowest_Z_Vert = min(Lowest_Z_Vert,z)
1995     Row += 1
1996     
1997     
1998     for i in range(180,80,-10):
1999         x = sin(radians(i))*RAD1
2000         z = cos(radians(i))*RAD1
2001         verts.append([(OUTSIDE_RADIUS-RAD1)+x,0.0,((Height_Offset - OVER_ALL_HEIGTH)+RAD1)+z])
2002         Lowest_Z_Vert = min(Lowest_Z_Vert,z)
2003         Row += 1
2004     
2005     
2006     x = OUTSIDE_RADIUS - 0
2007     z = Height_Offset 
2008     verts.append([x,0.0,z])
2009     Lowest_Z_Vert = min(Lowest_Z_Vert,z)
2010     Row += 1
2011
2012     sVerts,sFaces = SpinDup(verts,faces,360,DIV,'z')
2013     sVerts.extend(verts)        #add the start verts to the Spin verts to complete the loop
2014     
2015     faces.extend(Build_Face_List_Quads(FaceStart,Row-1,DIV,1))
2016
2017     return Move_Verts_Up_Z(sVerts,0),faces,Lowest_Z_Vert
2018
2019
2020
2021 def add_Nylon_Part(OUTSIDE_RADIUS,Z_LOCATION = 0):
2022     DIV = 36
2023     verts = []
2024     faces = []
2025     Row = 0
2026
2027     INNER_HOLE = OUTSIDE_RADIUS - (OUTSIDE_RADIUS * (1.5/4.75))
2028     EDGE_THICKNESS = (OUTSIDE_RADIUS * (0.4/4.75))
2029     RAD1 = (OUTSIDE_RADIUS * (0.5/4.75))
2030     OVER_ALL_HEIGTH = (OUTSIDE_RADIUS * (2.0/4.75))
2031     PART_THICKNESS = OVER_ALL_HEIGTH - EDGE_THICKNESS
2032     PART_INNER_HOLE = (OUTSIDE_RADIUS * (2.5/4.75))
2033     
2034     FaceStart = len(verts)
2035
2036     Start_Height = 0 - 3
2037     Height_Offset = Z_LOCATION
2038     Lowest_Z_Vert = 0
2039     
2040
2041     x = INNER_HOLE + EDGE_THICKNESS
2042     z = Height_Offset 
2043     verts.append([x,0.0,z])
2044     Lowest_Z_Vert = min(Lowest_Z_Vert,z)
2045     Row += 1
2046     
2047     x = PART_INNER_HOLE
2048     z = Height_Offset
2049     verts.append([x,0.0,z])
2050     Lowest_Z_Vert = min(Lowest_Z_Vert,z)
2051     Row += 1
2052     
2053     x = PART_INNER_HOLE
2054     z = Height_Offset - PART_THICKNESS
2055     verts.append([x,0.0,z])
2056     Lowest_Z_Vert = min(Lowest_Z_Vert,z)
2057     Row += 1
2058     
2059     x = INNER_HOLE + EDGE_THICKNESS
2060     z = Height_Offset - PART_THICKNESS
2061     verts.append([x,0.0,z])
2062     Lowest_Z_Vert = min(Lowest_Z_Vert,z)
2063     Row += 1
2064
2065
2066     sVerts,sFaces = SpinDup(verts,faces,360,DIV,'z')
2067     sVerts.extend(verts)  #add the start verts to the Spin verts to complete the loop
2068     
2069     faces.extend(Build_Face_List_Quads(FaceStart,Row-1,DIV,1))
2070
2071     return sVerts,faces,0 - Lowest_Z_Vert
2072
2073
2074
2075 def Nut_Mesh():
2076
2077     verts = []
2078     faces = []
2079     Head_Verts = []
2080     Head_Faces= []
2081
2082     Face_Start = len(verts)
2083     Thread_Verts,Thread_Faces,New_Nut_Height = Create_Internal_Thread(Minor_Dia.val,Major_Dia.val,Pitch.val,Hex_Nut_Height.val,Crest_Percent.val,Root_Percent.val,1)
2084     verts.extend(Thread_Verts)
2085     faces.extend(Copy_Faces(Thread_Faces,Face_Start))
2086     
2087     Face_Start = len(verts)
2088     Head_Verts,Head_Faces,Lock_Nut_Rad = add_Hex_Nut(Hex_Nut_Flat_Distance.val,Major_Dia.val,New_Nut_Height)
2089     verts.extend((Head_Verts))
2090     faces.extend(Copy_Faces(Head_Faces,Face_Start))
2091     
2092     LowZ = 0 - New_Nut_Height
2093     
2094     if Nut_Type['LOCK'][0].val:
2095         Face_Start = len(verts)
2096         Nylon_Head_Verts,Nylon_Head_faces,LowZ = add_Nylon_Head(Lock_Nut_Rad,0-New_Nut_Height)    
2097         verts.extend((Nylon_Head_Verts))
2098         faces.extend(Copy_Faces(Nylon_Head_faces,Face_Start))
2099     
2100         Face_Start = len(verts)
2101         Nylon_Verts,Nylon_faces,Temp_LowZ = add_Nylon_Part(Lock_Nut_Rad,0-New_Nut_Height)    
2102         verts.extend((Nylon_Verts))
2103         faces.extend(Copy_Faces(Nylon_faces,Face_Start))
2104     
2105
2106     return Move_Verts_Up_Z(verts,0 - LowZ),faces
2107
2108
2109
2110 ##################################################################################################
2111
2112
2113 def Create_Nut():
2114
2115     verts = []
2116     faces = []
2117     
2118   
2119     if Error_Check() :
2120         return
2121
2122     
2123     verts, faces = Nut_Mesh()
2124     Add_Mesh_To_Scene('Nut', verts, faces)
2125     
2126
2127 ##################################################################################################
2128
2129
2130 def Create_Bolt():
2131     verts = []
2132     faces = []
2133     
2134   
2135     if Error_Check() :
2136         return
2137     
2138     verts, faces = MakeBolt()
2139     Add_Mesh_To_Scene('Bolt', verts, faces)
2140
2141
2142
2143 def Remove_Doubles_From_Mesh(verts,faces):
2144     Ret_verts = []
2145     Ret_faces = []
2146     
2147     is_editmode = Window.EditMode() # Store edit mode state
2148     if is_editmode: Window.EditMode(0) # Python must get a mesh in object mode.
2149     
2150     Temp_mesh = Mesh.New('MeshTemp')          # create a new mesh
2151
2152     Temp_mesh.verts.extend(verts)          # add vertices to mesh
2153     Temp_mesh.faces.extend(faces)           # add faces to the mesh (also adds edges)
2154     
2155     scn = Scene.GetCurrent()          # link object to current scene
2156     Temp_Object = scn.objects.new(Temp_mesh, 'ObjectTemp')
2157
2158     Temp_mesh.remDoubles(0.010)
2159     Temp_mesh.transform(Mathutils.Matrix([Global_Scale,0,0,0], [0,Global_Scale,0,0], [0,0,Global_Scale,0], [0,0,0, Global_Scale]))
2160     Ret_verts[:] = [v.co for v in Temp_mesh.verts]
2161     Ret_faces[:] = [ [v.index for v in f] for f in Temp_mesh.faces]
2162
2163     #delete temp mesh
2164     scn.objects.unlink(Temp_Object)
2165     scn.update(0)
2166     
2167     if is_editmode: Window.EditMode(1)
2168     return Ret_verts,Ret_faces
2169
2170
2171
2172 def Add_Mesh_To_Scene(name, verts, faces):
2173  
2174     scn = Scene.GetCurrent()
2175     if scn.lib: return
2176     ob_act = scn.objects.active
2177
2178     is_editmode = Window.EditMode()
2179
2180     cursor = Window.GetCursorPos()
2181     quat = None
2182     
2183     if is_editmode or Blender.Get('add_view_align'): # Aligning seems odd for editmode, but blender does it, oh well
2184         try:    quat = Blender.Mathutils.Quaternion(Window.GetViewQuat())
2185         except:    pass
2186     
2187
2188     # Exist editmode for non mesh types
2189     if ob_act and ob_act.type != 'Mesh' and is_editmode:
2190         EditMode(0)
2191    
2192     # We are in mesh editmode
2193     if Window.EditMode():
2194         me = ob_act.getData(mesh=1)
2195         
2196         if me.multires:
2197             error_txt = 'Error%t|Unable to complete action with multires enabled'
2198             Blender.Draw.PupMenu(error_txt)
2199             print error_txt
2200             return
2201         
2202         #Don't want to remove doubles and scale the existing
2203         # mesh so we need to get the verts and the faces from
2204         # a mesh that has been scaled. 
2205         verts,faces = Remove_Doubles_From_Mesh(verts, faces)
2206                 
2207         # Add to existing mesh
2208         # must exit editmode to modify mesh
2209         Window.EditMode(0)
2210         
2211         me.sel = False
2212         
2213         vert_offset = len(me.verts)
2214         face_offset = len(me.faces)
2215         
2216         
2217         # transform the verts
2218         txmat = Blender.Mathutils.TranslationMatrix(Blender.Mathutils.Vector(cursor))
2219         if quat:
2220             mat = quat.toMatrix()
2221             mat.invert()
2222             mat.resize4x4()
2223             txmat = mat * txmat
2224         
2225         txmat = txmat * ob_act.matrixWorld.copy().invert()
2226         
2227         
2228         me.verts.extend(verts)
2229         # Transform the verts by the cursor and view rotation
2230         me.transform(txmat, selected_only=True)
2231         
2232         if vert_offset:
2233             me.faces.extend([[i+vert_offset for i in f] for f in faces])
2234         else:
2235             # Mesh with no data, unlikely
2236             me.faces.extend(faces)        
2237     else:
2238         
2239         # Object mode add new
2240         me = Mesh.New(name)
2241         me.verts.extend(verts)
2242         me.faces.extend(faces)
2243         
2244         
2245         me.sel = True
2246         
2247         # Object creation and location
2248         scn.objects.selected = []
2249         ob_act = scn.objects.new(me, name)
2250         
2251         me.remDoubles(0.010)
2252         me.transform(Mathutils.Matrix([Global_Scale,0,0,0], [0,Global_Scale,0,0], [0,0,Global_Scale,0], [0,0,0, Global_Scale]))
2253
2254         scn.objects.active = ob_act
2255         
2256         if quat:
2257             mat = quat.toMatrix()
2258             mat.invert()
2259             mat.resize4x4()
2260             ob_act.setMatrix(mat)
2261         
2262         ob_act.loc = cursor
2263     
2264     me.calcNormals()
2265     
2266     if is_editmode or Blender.Get('add_editmode'):
2267         Window.EditMode(1)
2268         
2269     Blender.Redraw(-1)#Redraw all
2270
2271 ##################################################################################################
2272     
2273     
2274
2275 def Load_Preset():
2276
2277     global Preset_Menu
2278     global Shank_Dia
2279     global Shank_Length
2280     global Thread_Length
2281     global Major_Dia 
2282     global Minor_Dia
2283     global Pitch 
2284     global Crest_Percent 
2285     global Root_Percent 
2286     global Allen_Bit_Flat_Distance
2287     global Allen_Bit_Depth
2288     global Head_Height
2289     global Hex_Head_Flat_Distance 
2290     global Head_Dia 
2291     global Dome_Head_Dia
2292     global Pan_Head_Dia 
2293     global Philips_Bit_Dia 
2294     global Phillips_Bit_Depth 
2295     global Cap_Head_Height
2296
2297     global Hex_Nut_Height
2298     global Hex_Nut_Flat_Distance
2299
2300
2301     if Preset_Menu.val == 1 : #M3
2302         Shank_Dia.val = 3.0
2303         #Pitch.val = 0.5    #Coarse
2304         Pitch.val = 0.35  #Fine
2305         Crest_Percent.val = 10
2306         Root_Percent.val = 10 
2307         Major_Dia.val = 3.0
2308         Minor_Dia.val = Major_Dia.val - (1.082532 * Pitch.val)
2309         Hex_Head_Flat_Distance.val = 5.5
2310         Hex_Head_Height.val = 2.0
2311         Cap_Head_Dia.val = 5.5
2312         Cap_Head_Height.val = 3.0
2313         Allen_Bit_Flat_Distance.val = 2.5
2314         Allen_Bit_Depth.val = 1.5
2315         Pan_Head_Dia.val = 5.6
2316         Dome_Head_Dia.val = 5.6
2317         Philips_Bit_Dia.val = Pan_Head_Dia.val*(1.82/5.6)
2318         Phillips_Bit_Depth.val = Get_Phillips_Bit_Height(Philips_Bit_Dia.val)
2319         Hex_Nut_Height.val = 2.4
2320         Hex_Nut_Flat_Distance.val = 5.5
2321         Thread_Length.val = 6
2322         Shank_Length.val = 0.0
2323         
2324     
2325     if Preset_Menu.val == 2 : #M4
2326         Shank_Dia.val = 4.0
2327         #Pitch.val = 0.7    #Coarse
2328         Pitch.val = 0.5  #Fine
2329         Crest_Percent.val = 10
2330         Root_Percent.val = 10 
2331         Major_Dia.val = 4.0
2332         Minor_Dia.val = Major_Dia.val - (1.082532 * Pitch.val)
2333         Hex_Head_Flat_Distance.val = 7.0
2334         Hex_Head_Height.val = 2.8
2335         Cap_Head_Dia.val = 7.0
2336         Cap_Head_Height.val = 4.0
2337         Allen_Bit_Flat_Distance.val = 3.0
2338         Allen_Bit_Depth.val = 2.0
2339         Pan_Head_Dia.val = 8.0
2340         Dome_Head_Dia.val = 8.0
2341         Philips_Bit_Dia.val = Pan_Head_Dia.val*(1.82/5.6)
2342         Phillips_Bit_Depth.val = Get_Phillips_Bit_Height(Philips_Bit_Dia.val)
2343         Hex_Nut_Height.val = 3.2
2344         Hex_Nut_Flat_Distance.val = 7.0
2345         Thread_Length.val = 8
2346         Shank_Length.val = 0.0
2347         
2348         
2349     if Preset_Menu.val == 3 : #M5
2350         Shank_Dia.val = 5.0
2351         #Pitch.val = 0.8 #Coarse
2352         Pitch.val = 0.5  #Fine
2353         Crest_Percent.val = 10
2354         Root_Percent.val = 10 
2355         Major_Dia.val = 5.0
2356         Minor_Dia.val = Major_Dia.val - (1.082532 * Pitch.val)
2357         Hex_Head_Flat_Distance.val = 8.0
2358         Hex_Head_Height.val = 3.5
2359         Cap_Head_Dia.val = 8.5
2360         Cap_Head_Height.val = 5.0
2361         Allen_Bit_Flat_Distance.val = 4.0
2362         Allen_Bit_Depth.val = 2.5
2363         Pan_Head_Dia.val = 9.5
2364         Dome_Head_Dia.val = 9.5
2365         Philips_Bit_Dia.val = Pan_Head_Dia.val*(1.82/5.6)
2366         Phillips_Bit_Depth.val = Get_Phillips_Bit_Height(Philips_Bit_Dia.val)
2367         Hex_Nut_Height.val = 4.0
2368         Hex_Nut_Flat_Distance.val = 8.0
2369         Thread_Length.val = 10
2370         Shank_Length.val = 0.0
2371         
2372         
2373     if Preset_Menu.val == 4 : #M6
2374         Shank_Dia.val = 6.0
2375         #Pitch.val = 1.0 #Coarse
2376         Pitch.val = 0.75  #Fine
2377         Crest_Percent.val = 10
2378         Root_Percent.val = 10
2379         Major_Dia.val = 6.0
2380         Minor_Dia.val = Major_Dia.val - (1.082532 * Pitch.val)
2381         Hex_Head_Flat_Distance.val = 10.0
2382         Hex_Head_Height.val = 4.0
2383         Cap_Head_Dia.val = 10.0
2384         Cap_Head_Height.val = 6.0
2385         Allen_Bit_Flat_Distance.val = 5.0
2386         Allen_Bit_Depth.val = 3.0
2387         Pan_Head_Dia.val = 12.0
2388         Dome_Head_Dia.val = 12.0
2389         Philips_Bit_Dia.val = Pan_Head_Dia.val*(1.82/5.6)
2390         Phillips_Bit_Depth.val = Get_Phillips_Bit_Height(Philips_Bit_Dia.val)
2391         Hex_Nut_Height.val = 5.0
2392         Hex_Nut_Flat_Distance.val = 10.0
2393         Thread_Length.val = 12
2394         Shank_Length.val = 0.0
2395         
2396         
2397     if Preset_Menu.val == 5 : #M8
2398         Shank_Dia.val = 8.0
2399         #Pitch.val = 1.25 #Coarse
2400         Pitch.val = 1.00  #Fine
2401         Crest_Percent.val = 10
2402         Root_Percent.val = 10
2403         Major_Dia.val = 8.0
2404         Minor_Dia.val = Major_Dia.val - (1.082532 * Pitch.val)
2405         Hex_Head_Flat_Distance.val = 13.0
2406         Hex_Head_Height.val = 5.3
2407         Cap_Head_Dia.val = 13.5
2408         Cap_Head_Height.val = 8.0
2409         Allen_Bit_Flat_Distance.val = 6.0
2410         Allen_Bit_Depth.val = 4.0
2411         Pan_Head_Dia.val = 16.0
2412         Dome_Head_Dia.val = 16.0
2413         Philips_Bit_Dia.val = Pan_Head_Dia.val*(1.82/5.6)
2414         Phillips_Bit_Depth.val = Get_Phillips_Bit_Height(Philips_Bit_Dia.val)
2415         Hex_Nut_Height.val = 6.5
2416         Hex_Nut_Flat_Distance.val = 13.0
2417         Thread_Length.val = 16
2418         Shank_Length.val = 0.0
2419     
2420     if Preset_Menu.val == 6 : #M10
2421         Shank_Dia.val = 10.0
2422         #Pitch.val = 1.5 #Coarse
2423         Pitch.val = 1.25  #Fine
2424         Crest_Percent.val = 10
2425         Root_Percent.val = 10
2426         Major_Dia.val = 10.0
2427         Minor_Dia.val = Major_Dia.val - (1.082532 * Pitch.val)
2428         Hex_Head_Flat_Distance.val = 17.0
2429         Hex_Head_Height.val = 6.4
2430         Cap_Head_Dia.val = 16.0
2431         Cap_Head_Height.val = 10.0
2432         Allen_Bit_Flat_Distance.val = 8.0
2433         Allen_Bit_Depth.val = 5.0
2434         Pan_Head_Dia.val = 20.0
2435         Dome_Head_Dia.val = 20.0
2436         Philips_Bit_Dia.val = Pan_Head_Dia.val*(1.82/5.6)
2437         Phillips_Bit_Depth.val = Get_Phillips_Bit_Height(Philips_Bit_Dia.val)
2438         Hex_Nut_Height.val = 8.0
2439         Hex_Nut_Flat_Distance.val = 17.0
2440         Thread_Length.val = 20
2441         Shank_Length.val = 0.0
2442     
2443     
2444     if Preset_Menu.val == 7 : #M12
2445         #Pitch.val = 1.75 #Coarse
2446         Pitch.val = 1.50  #Fine
2447         Crest_Percent.val = 10
2448         Root_Percent.val = 10
2449         Major_Dia.val = 12.0
2450         Minor_Dia.val = Major_Dia.val - (1.082532 * Pitch.val)
2451         Hex_Head_Flat_Distance.val = 19.0
2452         Hex_Head_Height.val = 7.5
2453         Cap_Head_Dia.val = 18.5
2454         Cap_Head_Height.val = 12.0
2455         Allen_Bit_Flat_Distance.val = 10.0
2456         Allen_Bit_Depth.val = 6.0
2457         Pan_Head_Dia.val = 24.0
2458         Dome_Head_Dia.val = 24.0
2459         Philips_Bit_Dia.val = Pan_Head_Dia.val*(1.82/5.6)
2460         Phillips_Bit_Depth.val = Get_Phillips_Bit_Height(Philips_Bit_Dia.val)
2461         Hex_Nut_Height.val = 10.0
2462         Hex_Nut_Flat_Distance.val = 19.0
2463         Shank_Dia.val = 12.0
2464         Shank_Length.val = 33.0
2465         Thread_Length.val = 32.0
2466         
2467 ##############################################################################################
2468
2469 def Test():
2470     verts = []
2471     faces = []
2472    
2473     if Error_Check() :
2474         return
2475     
2476     verts, faces = MakeBolt()
2477     
2478     Add_Mesh_To_Scene("TestBolt", verts,faces)
2479
2480     Window.Redraw(-1)
2481
2482
2483
2484
2485 def event(evt, val):    # the function to handle input events
2486
2487   if evt == Draw.ESCKEY:
2488     Draw.Exit()                 # exit when user presses ESC
2489     return
2490
2491
2492 def button_event(evt):  # the function to handle Draw Button events
2493
2494     if evt == On_Exit_Click:
2495         Draw.Exit()                 # exit when user presses ESC
2496         return
2497
2498     if evt == On_Test_Click:
2499         Test()
2500         Draw.Redraw(1)
2501     
2502     if evt == On_Preset_Click:
2503         Load_Preset()
2504         Draw.Redraw(1)
2505
2506     if evt == On_Create_Click:
2507         if Model_Type['BOLT'][0].val:
2508             Create_Bolt()
2509         if Model_Type['NUT'][0].val:
2510             Create_Nut()
2511         Draw.Redraw(1)
2512     
2513     elif (evt in [On_Hex_Click, On_Cap_Click,On_Dome_Click,On_Pan_Click]):
2514         for k in Head_Type.iterkeys():
2515             if Head_Type[k][1]!=evt:
2516                 Head_Type[k][0].val=0
2517             else:
2518                 Head_Type[k][0].val=1    
2519         Draw.Redraw(1)
2520     
2521     elif (evt in [On_Bit_None_Click,On_Bit_Allen_Click,On_Bit_Philips_Click]):
2522         for k in Bit_Type.iterkeys():
2523             if Bit_Type[k][1]!=evt:
2524                 Bit_Type[k][0].val=0
2525             else:
2526                 Bit_Type[k][0].val=1
2527         Draw.Redraw(1)
2528
2529     elif (evt in [On_Model_Bolt_Click,On_Model_Nut_Click]):
2530         for k in Model_Type.iterkeys():
2531             if Model_Type[k][1]!=evt:
2532                 Model_Type[k][0].val=0
2533             else:
2534                 Model_Type[k][0].val=1
2535         Draw.Redraw(1)
2536
2537     elif (evt in [On_Hex_Nut_Click,On_Lock_Nut_Click]):
2538         for k in Nut_Type.iterkeys():
2539             if Nut_Type[k][1]!=evt:
2540                 Nut_Type[k][0].val=0
2541             else:
2542                 Nut_Type[k][0].val=1
2543         Draw.Redraw(1)
2544     
2545 #####################################################################################
2546       
2547
2548 def Draw_Border(X1,Y1,X2,Y2): # X1,Y1 = Top Left X2,Y2 = Bottom Right
2549     INDENT = 3
2550     
2551     BGL.glColor3f(1.0,1.0,1.0)
2552     BGL.glBegin(BGL.GL_LINES)                
2553     BGL.glVertex2i(X1+INDENT,Y1-INDENT)     #top line
2554     BGL.glVertex2i(X2-INDENT,Y1-INDENT)
2555     
2556     BGL.glVertex2i(X1+INDENT,Y1-INDENT)     #left line
2557     BGL.glVertex2i(X1+INDENT,Y2+INDENT)
2558     BGL.glEnd()
2559
2560     BGL.glColor3f(0.5,0.5,0.5)
2561     BGL.glBegin(BGL.GL_LINES)                
2562     BGL.glVertex2i(X2-INDENT,Y1-INDENT)     #Right line
2563     BGL.glVertex2i(X2-INDENT,Y2+INDENT)
2564     
2565     BGL.glVertex2i(X1+INDENT,Y2+INDENT)     #bottom line
2566     BGL.glVertex2i(X2-INDENT,Y2+INDENT)
2567     BGL.glEnd()
2568     
2569     
2570
2571
2572 def Create_Tab(X1,Y1,X2,Y2,Title,Buttons): # X1,Y1 = Top Left X2,Y2 = Bottom Right
2573
2574     BIT_BUTTON_WIDTH = 55
2575     BIT_BUTTON_HEIGHT = 18
2576     TITLE_HEIGHT = 15
2577     INDENT = 6
2578     BUTTON_GAP = 4
2579
2580     BGL.glColor3f(0.75, 0.75, 0.75)
2581     BGL.glRecti(X1,Y1,X2,Y2)
2582     
2583     Draw_Border(X1,Y1,X2,Y2);
2584     
2585     BGL.glColor3f(0.0,0.0,0.0)
2586     BGL.glRasterPos2d(X1+INDENT,Y1 - TITLE_HEIGHT)
2587     Draw.Text(Title)
2588     
2589     Button_X = X1 + INDENT
2590     Button_Y = Y1 - TITLE_HEIGHT - BIT_BUTTON_HEIGHT - 8
2591     
2592     #Nut_Number_X = Nut_Button_X
2593     #Nut_Number_Y = Nut_Button_Y - 25
2594     if (Buttons != 0):
2595         key= Buttons.keys()
2596         for k in key:
2597             Buttons[k][0]= Draw.Toggle(k,Buttons[k][1],Button_X,Button_Y, BIT_BUTTON_WIDTH,BIT_BUTTON_HEIGHT,Buttons[k][0].val,Buttons[k][2])
2598             Button_X += BIT_BUTTON_WIDTH + BUTTON_GAP    
2599     
2600     
2601     
2602 def Dispaly_Title_Bar(Y_POS,CONTROL_HEIGHT):
2603     CONTROL_WIDTH = 250
2604     Create_Tab(3,Y_POS,CONTROL_WIDTH,Y_POS -CONTROL_HEIGHT,"Bolt Factory V2.02",Model_Type)
2605    
2606     
2607       
2608 def Dispaly_Preset_Tab(Y_POS,CONTROL_HEIGHT):
2609     CONTROL_WIDTH = 250
2610     BUTTON_Y_OFFSET = 40
2611     
2612     Create_Tab(3,Y_POS,CONTROL_WIDTH,Y_POS-CONTROL_HEIGHT,"Preset",0)
2613     
2614     name = "M3%x1|M4%x2|M5%x3|M6%x4|M8%x5|M10%x6|M12%x7"
2615     
2616     global Preset_Menu
2617     Preset_Menu = Draw.Menu(name,No_Event,9,Y_POS-BUTTON_Y_OFFSET,50,18, Preset_Menu.val, "Predefined metric screw sizes.")
2618     Draw.Button("Apply",On_Preset_Click,150,Y_POS-BUTTON_Y_OFFSET,55,18,"Apply the preset screw sizes.")
2619     
2620
2621 def Dispaly_Bit_Tab(Y_POS,CONTROL_HEIGHT):  
2622     
2623     CONTROL_WIDTH = 250
2624     NUMBER_HEIGHT = 18
2625     NUMBER_WIDTH = CONTROL_WIDTH  -3-3-3-3-3
2626
2627     Bit_Number_X = 3+3+3
2628     Bit_Number_Y = Y_POS - 64
2629         
2630     Create_Tab(3,Y_POS,CONTROL_WIDTH,Y_POS-CONTROL_HEIGHT,"Bit Type",Bit_Type)
2631     
2632     if Bit_Type['NONE'][0].val:
2633         DoNothing = 1;
2634         
2635     elif Bit_Type['ALLEN'][0].val:
2636         global Allen_Bit_Depth
2637         Allen_Bit_Depth = Draw.Number('Bit Depth: ',No_Event,Bit_Number_X,Bit_Number_Y,NUMBER_WIDTH, NUMBER_HEIGHT,Allen_Bit_Depth.val, 0,100, '')
2638         Bit_Number_Y -= NUMBER_HEIGHT
2639         global Allen_Bit_Flat_Distance
2640         Allen_Bit_Flat_Distance = Draw.Number('Flat Dist: ',No_Event,Bit_Number_X,Bit_Number_Y,NUMBER_WIDTH,NUMBER_HEIGHT,Allen_Bit_Flat_Distance.val, 0,100, '')
2641         Bit_Number_Y -= NUMBER_HEIGHT
2642
2643     elif Bit_Type['PHILLIPS'][0].val:
2644         global Phillips_Bit_Depth
2645         Phillips_Bit_Depth = Draw.Number('Bit Depth: ',No_Event,Bit_Number_X,Bit_Number_Y,NUMBER_WIDTH, NUMBER_HEIGHT,Phillips_Bit_Depth.val, 0,100, '')
2646         Bit_Number_Y -= NUMBER_HEIGHT
2647         global Philips_Bit_Dia
2648         Philips_Bit_Dia = Draw.Number('Bit Dia: ',No_Event,Bit_Number_X,Bit_Number_Y, NUMBER_WIDTH, NUMBER_HEIGHT,Philips_Bit_Dia.val, 0,100, '')
2649         Bit_Number_Y -= NUMBER_HEIGHT
2650
2651
2652
2653 def Dispaly_Shank_Tab(Y_POS,CONTROL_HEIGHT):  
2654     
2655     CONTROL_WIDTH = 250
2656     NUMBER_HEIGHT = 18
2657     NUMBER_WIDTH = CONTROL_WIDTH  -3-3-3-3-3
2658
2659     Number_X = 3+3+3
2660     Number_Y_Pos = Y_POS - 40
2661         
2662     Create_Tab(3,Y_POS,CONTROL_WIDTH,Y_POS-CONTROL_HEIGHT,"Shank",0)
2663   
2664     global Shank_Length 
2665     Shank_Length = Draw.Number('Shank Length: ',No_Event,Number_X,Number_Y_Pos,NUMBER_WIDTH,NUMBER_HEIGHT, Shank_Length.val, 0,MAX_INPUT_NUMBER, 'some text tip')
2666     Number_Y_Pos -= NUMBER_HEIGHT
2667   
2668     global Shank_Dia 
2669     Shank_Dia = Draw.Number('Shank Dia: ',No_Event,Number_X,Number_Y_Pos,NUMBER_WIDTH,NUMBER_HEIGHT, Shank_Dia.val, 0,MAX_INPUT_NUMBER, 'some text tip')
2670     Number_Y_Pos -= NUMBER_HEIGHT
2671   
2672     
2673
2674 def Dispaly_Thread_Tab(Y_POS,CONTROL_HEIGHT):  
2675     
2676     CONTROL_WIDTH = 250
2677     NUMBER_HEIGHT = 18
2678     NUMBER_WIDTH = CONTROL_WIDTH  -3-3-3-3-3
2679     
2680
2681     Number_X = 3+3+3
2682     Number_Y_Pos = Y_POS - 40
2683             
2684     Create_Tab(3,Y_POS,CONTROL_WIDTH,Y_POS-CONTROL_HEIGHT,"Thread",0)
2685     
2686     global Thread_Length
2687     if Model_Type['BOLT'][0].val:
2688         Thread_Length = Draw.Number('Thread Length: ',No_Event, Number_X,Number_Y_Pos,NUMBER_WIDTH,NUMBER_HEIGHT, Thread_Length.val, 0,MAX_INPUT_NUMBER, '')
2689     Number_Y_Pos -= NUMBER_HEIGHT
2690   
2691     global Major_Dia
2692     Major_Dia = Draw.Number('Major Dia: ',No_Event,Number_X,Number_Y_Pos, NUMBER_WIDTH,NUMBER_HEIGHT, Major_Dia.val, 0,MAX_INPUT_NUMBER, '')
2693     Number_Y_Pos -= NUMBER_HEIGHT
2694   
2695     global Minor_Dia
2696     Minor_Dia = Draw.Number('Minor Dia: ',No_Event,Number_X,Number_Y_Pos, NUMBER_WIDTH,NUMBER_HEIGHT, Minor_Dia.val, 0,MAX_INPUT_NUMBER, '')
2697     Number_Y_Pos -= NUMBER_HEIGHT
2698   
2699     global Pitch
2700     Pitch = Draw.Number('Pitch: ',No_Event,Number_X,Number_Y_Pos,NUMBER_WIDTH,NUMBER_HEIGHT, Pitch.val, 0.1,7.0, '')
2701     Number_Y_Pos -= NUMBER_HEIGHT
2702     
2703     global Crest_Percent
2704     Crest_Percent = Draw.Number('Crest %: ',No_Event,Number_X,Number_Y_Pos,NUMBER_WIDTH,NUMBER_HEIGHT,Crest_Percent.val, 1,90, '')
2705     Number_Y_Pos -= NUMBER_HEIGHT
2706   
2707     global Root_Percent
2708     Root_Percent = Draw.Number('Root %: ',No_Event,Number_X,Number_Y_Pos,NUMBER_WIDTH,NUMBER_HEIGHT,Root_Percent.val, 1,90, '')
2709     Number_Y_Pos -= NUMBER_HEIGHT
2710   
2711
2712     
2713     
2714 def Dispaly_Head_Tab(Y_POS,CONTROL_HEIGHT):  
2715     
2716     CONTROL_WIDTH = 250
2717     NUMBER_HEIGHT = 18
2718     NUMBER_WIDTH = CONTROL_WIDTH  -3-3-3-3-3
2719
2720     Head_Number_X = 3+3+3
2721     Head_Number_Y = Y_POS - 64
2722         
2723     Create_Tab(3,Y_POS,CONTROL_WIDTH,Y_POS-CONTROL_HEIGHT,"Head Type",Head_Type)
2724     
2725     if Head_Type['HEX'][0].val:  
2726         global Hex_Head_Height
2727         Hex_Head_Height = Draw.Number('Head Height: ',No_Event,Head_Number_X ,Head_Number_Y, NUMBER_WIDTH, NUMBER_HEIGHT,Hex_Head_Height.val, 0,100, '')
2728         Head_Number_Y -= NUMBER_HEIGHT
2729         global Hex_Head_Flat_Distance
2730         Hex_Head_Flat_Distance = Draw.Number('Head Hex Flat Distance ',No_Event,Head_Number_X,Head_Number_Y,NUMBER_WIDTH, NUMBER_HEIGHT,Hex_Head_Flat_Distance.val, 0,MAX_INPUT_NUMBER, '')
2731         Head_Number_Y -= NUMBER_HEIGHT
2732   
2733     elif Head_Type['CAP'][0].val:  
2734         global Cap_Head_Height
2735         Cap_Head_Height = Draw.Number('Head Height: ',No_Event, Head_Number_X,Head_Number_Y, NUMBER_WIDTH, NUMBER_HEIGHT,Cap_Head_Height.val, 0,100, '')
2736         Head_Number_Y -= NUMBER_HEIGHT
2737         global Cap_Head_Dia
2738         Cap_Head_Dia = Draw.Number('Head Dia ',No_Event,Head_Number_X,Head_Number_Y,NUMBER_WIDTH, NUMBER_HEIGHT,Cap_Head_Dia.val, 0,MAX_INPUT_NUMBER, '')
2739         Head_Number_Y -= NUMBER_HEIGHT
2740   
2741     elif Head_Type['DOME'][0].val:  
2742         global Dome_Head_Dia
2743         Dome_Head_Dia = Draw.Number(' Dome Head Dia ',No_Event,Head_Number_X,Head_Number_Y, NUMBER_WIDTH, NUMBER_HEIGHT,Dome_Head_Dia.val, 0,MAX_INPUT_NUMBER, '')
2744         Head_Number_Y -= NUMBER_HEIGHT
2745   
2746     elif Head_Type['PAN'][0].val:  
2747         global Pan_Head_Dia
2748         Pan_Head_Dia = Draw.Number('Pan Head Dia ',No_Event,Head_Number_X,Head_Number_Y, NUMBER_WIDTH, NUMBER_HEIGHT,Pan_Head_Dia.val, 0,MAX_INPUT_NUMBER, '')
2749         Head_Number_Y -= NUMBER_HEIGHT
2750   
2751     
2752     
2753     
2754 def Dispaly_Nut_Tab(Y_POS,CONTROL_HEIGHT):  
2755     
2756     CONTROL_WIDTH = 250
2757     NUMBER_HEIGHT = 18
2758     NUMBER_WIDTH = CONTROL_WIDTH  -3-3-3-3-3
2759
2760     Nut_Number_X = 3+3+3
2761     Nut_Number_Y = Y_POS - 64
2762    
2763     Create_Tab(3,Y_POS,CONTROL_WIDTH,Y_POS-CONTROL_HEIGHT,"Nut Type",Nut_Type)
2764         
2765     #if Nut_Type['HEX'][0].val:  
2766     global Hex_Nut_Height
2767     Hex_Nut_Height = Draw.Number('Nut Height: ',No_Event,Nut_Number_X ,Nut_Number_Y, NUMBER_WIDTH, NUMBER_HEIGHT,Hex_Nut_Height.val, 0,MAX_INPUT_NUMBER, '')
2768     Nut_Number_Y -= NUMBER_HEIGHT
2769     global Hex_Nut_Flat_Distance
2770     Hex_Nut_Flat_Distance = Draw.Number('Nut Flat Distance ',No_Event,Nut_Number_X,Nut_Number_Y, NUMBER_WIDTH, NUMBER_HEIGHT,Hex_Nut_Flat_Distance.val, 0,MAX_INPUT_NUMBER, '')
2771     Nut_Number_Y -= NUMBER_HEIGHT
2772   
2773
2774 def Dispaly_Bolt_Tab():    
2775        
2776     Dispaly_Shank_Tab(284,66)
2777     Dispaly_Head_Tab(374,90)
2778     Dispaly_Bit_Tab(464,90)
2779     
2780
2781 ##########################################################################################
2782
2783 def gui():              # the function to draw the screen
2784     
2785     CONTROL_WIDTH = 250
2786
2787     BGL.glClearColor(0.6, 0.6, 0.6, 1.0)
2788     BGL.glClear(BGL.GL_COLOR_BUFFER_BIT)
2789     
2790     BGL.glColor3f(0.75, 0.75, 0.75)
2791     BGL.glRecti(3,30,CONTROL_WIDTH,3)
2792     
2793     Dispaly_Title_Bar(514,50);
2794     
2795     if Model_Type['BOLT'][0].val:
2796         Dispaly_Bolt_Tab();
2797     
2798     if Model_Type['NUT'][0].val:
2799         Dispaly_Nut_Tab(464,246);
2800
2801     Dispaly_Thread_Tab(218,138)
2802
2803     Dispaly_Preset_Tab(80,50)
2804     
2805     Draw.PushButton("Create",On_Create_Click,6,8,55,18,"Create Bolt")
2806     Draw.Button("Exit",On_Exit_Click,6+55+4,8,55,18)
2807    
2808 #    Draw.Button("Test",On_Test_Click,150,10,55,20)
2809
2810 Load_Preset()
2811 Draw.Register(gui, event, button_event)  # registering the 3 callbacks