## KickerAngle.py Version 1.01
## Copyright (c)
2007 Bruce Vaughan, BV Detailing & Design, Inc.
## All rights
reserved.
## NOT FOR
################################################################################
"""
This script will add a miscellaneous 'Angle' rolled shape kicker and kicker
gusset plates to a
W flange or Tube beam by picking points while in plan.
The kicker and plates will be oriented
vertically.
Thickness reference point on the plate
material is "Center".
A pin hole and bolt can be added to the
plate material and kicker at the
high end or both
ends. The gage on the angle will be the leg width/2.
The user selects a series of point pairs
(one on each supporting member)
and identifies
which end is at the beam bottom flange (1st or 2nd point).
**NOTE: Point 1 must be on Member 1 and
Point 2 must be on Member 2.**
**USAGE NOTE: The pin hole
gages on the gusset plates and kicker edge
distance at
pin are used to calculate the working point for the
kicker angle
even though pin holes may not be installed.
Version 1.00 (
Version 1.01 (
************************************************************
****NOTE: This script can only be executed
in plan**********
****NOTE: This version is not compatible
with
************************************************************
Developed in
Developed by Bruce Vaughan, BV Detailing
& Design, Inc. (BVD)
For comments, suggestions or questions call
BV at the number above, email
bvaughan@bvdetailing
or post to
"""
def run_script():
import os
# startup code
begin
from math import cos, floor, pi, tan, sin, atan
from param import yes_or_no, ResponseNotOK, Units, ClearSelection
from param import Dialog, dim_print,
Warning, dim
from macrolib.FileDefaults import import_data,
export_data
# macrolib.pickle
required
from macrolib.MemSelection import mem_select
# macrolib.MemCnt
required
from macrolib.Weld import mtrl_weld
from macrolib.ExceptWarn import formatExceptionInfo
from macrolib.angle import rtod, dtor, angle_between_mem_pts, planRotPts, rotation_test
from macrolib.kicker import kicker_pl,
gpl_hole, add_kicker_pl, add_kicker
from macrolib.PolarPt import PolarPt3D
from
macrolib.Basis3D import BasisTransToGlobal, BasisTransToLocal
from macrolib.P3D
import Plane3D
from macrolib.round_length import round_length_next
from macrolib.PrintPtList import formatPtList
from macrolib.bolt_match import bolt_match
Units("feet")
from shape import
Shape
from point import
Point, PointLocate
from member import
Member, MemberLocate
from mtrl_list import MtrlLocate, HoleLocate
from rect_plate import RectPlate
from rolled_section import RolledSection
from hole_add import Hole
from bolt_add import Bolt
from mtrl_fit import MtrlFit
from job import
Job
from fab import Fabricator
from mtrl_cut import MtrlCut
# startup code end
## Variables Section
################################################
# system path for
defaults file
default_file_path
= os.path.join(os.getcwd(), "macro",
"Defaults")
# defaults file
def_file =
"KickerAngle.txt"
# Dialog box image path and file name
image_path = os.path.join(os.getcwd(), "macro", "Images")
# Dialog box image path and file name
image_name1 = os.path.join(image_path, "KickerAngle1.gif")
image_name2 = os.path.join(image_path, "KickerAngle2.gif")
image_name3 = os.path.join(image_path, "KickerAngle3.gif")
image_name4 = os.path.join(image_path, "KickerAngle4.gif")
# Enable or disable import/export dialog
dictionary variables
# ["Enable" "Disable"]
enable_default_import_export
= "Enable"
finishList =
["None", "Red Oxide", "Yellow Zinc", "Gray
Oxide", "Sandblasted", "Blued Steel",
"Galvanized"]
holeTypeList
= ["Standard Round", "Short Slot", "Oversized
Round", "Long Slot"]
boltTypeList
= Job().bolt_sched()
mtrlGradeList
= Job().steel_grades("Plate").keys()
weldSizeList
= ['3/16', '1/4', '5/16']
pinList
= ("High End", "Both Ends", "None")
rndList
= ('0', '1/16', '1/8', '1/4', '1/2', '1')
## Defaults Section
#############################################
# ('NS', 'FS')
which_sidePlate =
'NS'
# ('Point 1', 'Point 2')
whichIsHigh
= ('Point 2')
# plate offset
from the selected point locations
points_x_offset =
-0.1875
# plate rotation
from the orthogonal
theta = 0.0
# side(s) for gusset plates
("BS", "NS", "FS")
which_side =
"BS"
# add plate at top
or bottom flange ("Top", "Bott",
"T&B")
top_or_bott =
"Bott"
# plate width
(width is vertical)
gpl_width = 5.0
# plate length
(length is horizontal)
gpl_length = 5.0
# plate thickness
gpl_thk = 0.375
# plate clip
dimension
gpl_clip = 1.0
# set plates
normal to beam or vertical ("Normal", "Vertical")
norm_or_vert =
"
matlcolor
= "Yellow Zinc"
matlgrade
= "A36"
kickmtrl
= "L3x3x1/4"
kickgrade
= "A36"
kick_ed = 1.5
# round off kicker
length to the next increment
# ('0', '1/16', '1/8', '1/4', '1/2', '1')
rnd_inc = '1/2'
# "User" "System"
Create user piece mark or system piece mark
mark_system_user
= "User"
user_piece_mark =
"K_01"
# add hole for erection bolt ("High
End", "Both Ends", "None")
pin_hole =
"High End"
# horizontal gage,
distance from plate edge
x_ga = 3.0
# vertical gage,
distance from plate edge
y_ga = 3.0
bolt_size = 0.75
bolt_type =
"A325"
hole_type =
"Standard Round"
# long slot length
where applicable - calculate if = 0"
long_slot_length
= 0.0
# add weld ("Yes", "No")
add_gpl_weld =
"Yes"
# weld type
("Fillet", "Square butt")
gpl_weld_type =
"Fillet"
weld_size =
"3/16"
## end Defaults and Variables Section
###############################
#####################################################################
## Import defaults data if enabled
if enable_default_import_export == "Enable":
dd0 = import_data(os.path.join(default_file_path, def_file))
if dd0:
for key,
value in dd0.items():
exec
"%s = %s" % (key, repr(value)) in None
#####################################################################
## Main program loop
# Select member
while True:
# Select two members
bm_list1 = mem_select("Select a WF or
HSS
if bm_list1 is
None:
break
mem1 = bm_list1[0]
bm_list2 = mem_select("Select another
WF or HSS
if bm_list2 is
None:
break
mem2 = bm_list2[0]
#############################################################
## DIALOG
#############################################################
dlg1 = Dialog("Add
kicker gusset plates")
dlg1.menu("print_doc", ("Yes", "No"),
"No", "Print documentation only")
dlg1.tabset_begin()
dlg1.tab("General
Information")
dlg1.group_title("Kicker
point pairs will be selected after dialog box")
dlg1.menu('which_sidePlate', ('NS', 'FS'), which_sidePlate,
'Which side of kicker plates ')
dlg1.menu('whichIsHigh', ('Point 1', 'Point 2'), whichIsHigh,
'Which POINT is HIGH')
dlg1.entry("points_x_offset", dim_print(points_x_offset), "Member 'X' offset distance from
selected points to PL CL")
dlg1.menu('rnd_inc', rndList, rnd_inc, 'Round off length to the next increment')
dlg1.group_title_end()
dlg1.group_title("Kicker
material")
dlg1.entry("kickmtrl", kickmtrl, 'Kicker
material ')
dlg1.menu("mark_system_user", ("User",
"System"), mark_system_user, "User or
System Piece Mark")
dlg1.entry("user_piece_mark", user_piece_mark,
"User Piece Mark")
dlg1.entry("kick_ed" , dim_print(kick_ed), 'Edge distance at pin')
dlg1.menu("kickgrade", Job().steel_grades("Angle").keys(),
matlgrade, "Material grade")
dlg1.group_title_end()
dlg1.group_title("Kicker
Plate Material")
dlg1.entry("gpl_width", dim_print(gpl_width), "Plate width (vertical)")
dlg1.entry("gpl_length", dim_print(gpl_length), "Plate length (horizontal)")
dlg1.entry("gpl_thk", dim_print(gpl_thk), "Plate thickness")
dlg1.entry("gpl_clip", dim_print(gpl_clip), "Clip dimension")
dlg1.menu("matlcolor", finishList, matlcolor, "Material finish" )
dlg1.menu("matlgrade", Job().steel_grades("Plate").keys(),
matlgrade, "Material grade")
dlg1.group_title_end()
dlg1.group_title("Additional
Options")
dlg1.menu("pin_hole", pinList, pin_hole, "Add a pin hole and bolt")
dlg1.menu("add_gpl_weld", ("Yes", "No"), add_gpl_weld, "Add weld" )
dlg1.group_title_end()
dlg1.tab("Pin
Hole Information")
dlg1.group_title("Dimensions")
dlg1.entry("x_ga", dim_print(x_ga), "Horizontal gage from edge of plate")
dlg1.entry("y_ga", dim_print(y_ga), "Vertical gage from edge of plate")
dlg1.group_title_end()
dlg1.group_title("Bolt
Information")
dlg1.entry("bolt_size", dim_print(bolt_size), "Enter bolt size")
dlg1.menu("bolt_type",
Job().bolt_sched(), bolt_type,
"Bolt type in plate")
dlg1.group_title_end()
dlg1.group_title("Hole
Information")
dlg1.menu("hole_type", holeTypeList, hole_type, "Hole type in plate")
dlg1.group_title_end()
dlg1.group_title("'long
slot length' = 0 to calculate length")
dlg1.entry("long_slot_length", dim_print(long_slot_length), "Slot length (applies to 'Long
Slot')")
dlg1.group_title_end()
dlg1.group_title("Graphic
Image")
dlg1.image(image_name3)
dlg1.group_title_end
dlg1.tab("Weld
Information")
dlg1.group_title("Welding
Data")
dlg1.menu("gpl_weld_type", ("Fillet", "Square
butt", "Bevel groove"), gpl_weld_type,
"Weld type
" )
dlg1.menu("weld_size", ("3/16", "1/4",
"5/16"), weld_size, "Weld size")
dlg1.group_title_end()
dlg1.group_title("Graphic
Image")
dlg1.image(image_name4)
dlg1.group_title_end
dlg1.tab("Graphic
Image")
#dlg1.column_group_begin()
#dlg1.column(0)
dlg1.group_title("'X'
Kickers - 2 Loops required")
dlg1.image(image_name1)
dlg1.group_title_end()
#dlg1.column(0)
dlg1.group_title("Kicker
skewed with respect to beams")
dlg1.image(image_name2)
dlg1.group_title_end()
#dlg1.column_group_end()
dlg1.tabset_end()
try:
dd1 = dlg1.done()
except ResponseNotOK:
break
# Update the local namespace for next
loop
for key, value
in dd1.items():
exec
"%s = %s" % (key, repr(value)) in None
###############################################################
## END DIALOG
###############################################################
if print_doc == "Yes":
print
__doc__
break
##############################################################
# Export defaults to disk if enabled
if enable_default_import_export == "Enable":
export_data(os.path.join(default_file_path, def_file),
dd1)
###############################################################
pt_list =
[]
while True:
pt1 = PointLocate("Select
Point 1 or return")
if pt1 is None:
break
pt2 = PointLocate("Select
Point 2")
if pt2 ==
None:
break
else:
pt_list.append([pt1, pt2])
## Prepare to add gusset plates
#########
dd1['norm_or_vert'] = 'Vertical'
# If beam is a
Tube, clipped corners are not required
if
mem1.mtrl_type == "Tube":
dd1['gpl_clip'] = 0.0
## Add gusset 1
#########################
# Determine
side and T or B member 1
if whichIsHigh == 'Point 1':
dd1['top_or_bott'] = 'Top'
else:
dd1['top_or_bott'] = 'Bott'
if pin_hole == "High End" and dd1['top_or_bott'] == 'Top':
dd1['add_pin_hole'] = 'Yes'
elif
pin_hole == "Both Ends":
dd1['add_pin_hole'] = 'Yes'
else:
dd1['add_pin_hole'] = 'No'
rp_list1 = []
for t in pt_list:
pt =
mem1.trans_to_local(t[1] - mem1.left.location)
if pt.z > 0:
dd1['which_side'] = 'NS'
else:
dd1['which_side'] = 'FS'
# Calculate
theta
dd1['theta']
= rtod(atan(tan(angle_between_mem_pts(mem1, t[0], t[1])) / cos(dtor(mem1.slope))))
rp_list1 += add_kicker_pl([t[0], ], [mem1, ], dd1)
## Add gusset 2
#########################
# Determine
side and T or B member 2
if whichIsHigh == 'Point 1':
dd1['top_or_bott'] = 'Bott'
else:
dd1['top_or_bott'] = 'Top'
if pin_hole == "High End" and dd1['top_or_bott'] == 'Top':
dd1['add_pin_hole'] = 'Yes'
elif
pin_hole == "Both Ends":
dd1['add_pin_hole'] = 'Yes'
else:
dd1['add_pin_hole'] = 'No'
rp_list2 = []
for t in pt_list:
pt =
mem2.trans_to_local(t[0] - mem2.left.location)
if pt.z > 0:
dd1['which_side'] = 'NS'
else:
dd1['which_side'] = 'FS'
# Calculate
theta
dd1['theta']
= rtod(atan(tan(angle_between_mem_pts(mem2, t[0], t[1]))) * cos(dtor(mem1.slope)))
rp_list2 += add_kicker_pl([t[1], ], [mem2, ], dd1)
if mark_system_user == "System":
mk = ""
else:
mk = user_piece_mark
for rp1, rp2
in zip(rp_list1, rp_list2):
if whichIsHigh == 'Point 1':
high =
1
else:
high =
-1
ptWP1 = rp1.pt1 + rp1.trans_to_global(x_ga, -y_ga,
0.0)
ptWP2 = rp2.pt1 + rp2.trans_to_global(x_ga, -y_ga,
0.0)
localBasis = BasisTransToGlobal(ptWP1, ptWP2, rp1.pt1
+ rp1.trans_to_global(gpl_length, 0.0, 0.0))
leg_ga = max(Shape(kickmtrl).depth/2,
1.375)
pt_to_pt
= ptWP1.dist(ptWP2)
kick_len
= round_length_next(pt_to_pt + kick_ed*2,
rnd_inc)
end_dist
= (kick_len-pt_to_pt)/2
if which_sidePlate == 'NS':
side =
1
leg_dir
= 'In'
rot =
(90.0, 0.0, 0.0)
else:
side =
-1
leg_dir
= 'Out'
rot = (90.0, 0.0,
0.0)
# print formatPtList('Work points', [ptWP1, ptWP2])
memPt1 = ptWP1 + localBasis.translate(-end_dist, high*leg_ga, high*side*gpl_thk/2)
memPt2 = ptWP2 + localBasis.translate(end_dist, high*leg_ga, high*side*gpl_thk/2)
# print formatPtList('Calculated points', [memPt1, memPt2])
# print formatPtList('Difference between points', [memPt1-ptWP1,
memPt2-ptWP2])
if not rotation_test(planRotPts(memPt1,
memPt2)):
rot =
(rot[0], 0.0, 180.0)
angle1 = add_kicker(memPt1, memPt2, kickmtrl, kickgrade, mk, 'HZ.', leg_dir, rot)
if pin_hole == "High End" and whichIsHigh
== 'Point 1':
gpl_hole(angle1, ptWP1, '
bolt_match(angle1.main_mtrl(),
[rp1, ])
elif pin_hole == "High
End" and whichIsHigh == 'Point 2':
gpl_hole(angle1, ptWP2, '
bolt_match(angle1.main_mtrl(),
[rp2, ])
elif pin_hole == "Both
Ends":
gpl_hole(angle1, ptWP1, '
gpl_hole(angle1, ptWP2, '
bolt_match(angle1.main_mtrl(),
[rp1, rp2])
if not yes_or_no("Add kicker gusset plates to another member?"):
break
## End run_script()
if __name__ == '__main__':
try:
run_script()
finally: