Back to SDS/2 Parametric Scripts

##  Beam_MomentClip.py Version 1.02

##  Copyright (c) 2006 Bruce Vaughan, BV Detailing & Design, Inc.

##  All rights reserved.

##  NOT FOR SALE. The software is provided "as is" without any warranty.

############################################################################

"""

    Add end moment clips to a WF, Tube or Channel beam.

    This script can be executed in plan, elevation, or isometric.

    The script reads the beam end minus dimension to set the clip angle locations.

    If beam has plain end, set the minus dimension to the face of supporting member.

    Reprocess the members to match holes and add bolts.

 

    Originally developed in SDS2 6.232, Python 1.5.1    5/10/02

    Tested in SDS2 6.322, Python 2.2.1 10/14/03

    Developed by Bruce Vaughan, BV Detailing & Design, Inc. (BVD)  (615) 646-9239

    For comments, suggestions or questions call BVD at the number above.

     

    NOT FOR SALE

 

    R1 -    Updated code (10/14/03)

    R2 -    Reworked dialog box (4/30/04)

    V7R1 -  Tested in SDS/2 7.002, updated code

    Version 1.00 (3/12/07) - Rewrote using modules

                             Updated code

    Version 1.01 (3/28/07) - Add option to extend clip beyond minus dimension

    Version 1.02 (3/31/07) - Correction line 231, 232

 

    Go to Defaults section to modify script defaults.

"""

def run_script():

    # startup code begin

    from math import cos, floor, pi, tan

    from param import yes_or_no, ResponseNotOK, Units, ClearSelection, Dialog, dim_print, Warning, dim

    from macrolib.FileDefaults import import_data, export_data  # macrolib.pickle required

    from macrolib.MemCnt import member_count

    from macrolib.Weld import mtrl_weld

    from macrolib.ColumnFraming import ColumnSupport, ColumnCondition

    from macrolib.MemSelection import mem_select

   

    import os

    import sys

    Units("feet")

    from shape import Shape

    from point import Point, PointLocate

    from member import Member, MemberLocate, MemberAllocated

    from rolled_section import RolledSection

    from weld_add import Weld

    from job import Job

    from fab import Fabricator

    from hole_add import Hole

    from bolt_add import Bolt

    # startup code end

    #################################################################

    ## Variables section ############################################

    # system path for defaults file

    default_file_path = os.path.join(os.getcwd(), "macro", "Defaults")

    # defaults file

    def_file = "Beam_MomentClip.txt"

 

    # Dialog box image path and file name

    image_path = os.path.join(os.getcwd(), "macro", "Images")

    image_name1 = os.path.join(image_path, "Beam_MomentClip.gif")

    image_name2 = os.path.join(image_path, "Beam_MomentClip1.gif")

    image_name3 = os.path.join(image_path, "Beam_MomentClip2.gif")

    # image_name7 = os.path.join(image_path, "PurlinRafterBanner1.gif")

    # default to enable or disable the importing and exporting of 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"]

    holeTypeList1 = ["Standard Round", "Oversized Round"]   

 

    wsList = ['3/16', '1/4', '5/16', '3/8']   

    ## Defaults section #############################################

    # extend clip beyond member minus dimension

    extend_clip = 1.0

    # end to add moment clip "Left" "Right" "Both"

    which_end = "Right"

    # top or bottom of beam "Top", "Bott", "Both"

    t_or_b = "Both"

    # clip angle size

    clip_size = "L4x4x1/2"

    # long leg vertical or horizontal where applicable

    llv_llh = "LLV"

    # Job().steel_grades("Angle").keys()

    steelgrade = "A36"

    # finishList

    clip_finish = "Yellow Zinc"

    # add weld       "Yes" "No"

    add_clip_weld = "Yes"

    # weld type "Fillet"

    clip_weld_type = "Fillet"

   

    # weld size - wsList

    weld_size = 0.25

   

    col_leg_ga = 4.0                        # default hole centers(0" for 1 bolt)

    clip_gage = 2.5                         # default gage of clip angle OSL

    dbl_gage_spa = 3.0                      # default double gage spacing - 0" for single gage only

    edge_dist = 1.5                         # default edge distance

    bolt_size = 0.75                        # bolt diameter

 

    # holeTypeList - leg against column

    hole_type_col = "Standard Round"

    # bolt type against column Job().bolt_sched()

    bolt_type_col = "A325N"

    #  slot rotation if applicable "VT.", "HZ."

    slot_rot = "VT."

   

    # Beam flange holes

    # add flange holes in beam

    add_flg_hls = "No"

    # gage of clip angle FLG leg

    clip_gage1 = 2.5

    # double gage spacing in FLG leg- 0" for single gage only

    dbl_gage_spa1 = 0.0

    # bolt diameter

    bolt_size1 = 0.75

    # hole type in leg against beam - holeTypeList

    hole_type_flg = "Standard Round"

    # bolt type in leg against beam Job().bolt_sched()

    bolt_type_flg = "A325N"

    # slot rotation if applicable "VT.", "HZ."

    slot_rot1 = "VT."

 

    ###################################################################

    ## Function definition section

    # Function to add angle material

    def add_clip(mem, pt1, pt2, size, grade, finish, orient, rot_args):

        # rolled section begin

        rl6 = RolledSection()

        rl6.member = mem

        rl6.pt1 = pt1

        rl6.pt2 = pt2

        rl6.section_size = size

        rl6.grade = grade

        rl6.centered = 'No'

        rl6.llv = orient

        rl6.toe_io = "In"

        rl6.work_pt_dist = pt1.dist(pt2)

        rl6.setback_left = 0

        rl6.setback_right = 0

        rl6.end_cut_left = "Standard Cut"

        rl6.end_cut_right = "Standard Cut"

        rl6.length = pt1.dist(pt2)

        rl6.mtrl_type = 'Angle'

        rl6.finish = finish

        rl6.ref_pt_offset = (0.000000, 0.000000, 0.000000)

        rl6.add()

        rl6.rotate(rl6.member, rot_args)

        # rolled section end

        return rl6

 

    # Function to add holes in clip angle

    def moment_clip_hole (mat, pt1, ht, hl_face, x_off, y_off, dgs, hole_rot, bt, db, gr):

        if dgs >= 2.6667*db:

            no_row = 2

        else:

            no_row = 1

        try:

            # hole group add begin

            hole26 = Hole()

            hole26.mtrl = [mat, ]

            hole26.pt1 = pt1 # + mat.translate(0.0, 0.0, y_off)

            hole26.hole_type = ht

            hole26.face = hl_face

            hole26.valid_cnc = "Yes"

            hole26.x_ref_offset = x_off

            hole26.y_ref_offset = y_off

            hole26.x_spa = 0.0

            hole26.y_spa = dgs 

            hole26.group_rot = gr

            hole26.locate = "Above"

            hole26.columns = 1

            hole26.rows = no_row

            hole26.bolt_type = bt

            hole26.bolt_dia = db

            hole26.slot_rot = hole_rot

            hole26.length = hole26.calc_slot_length()

            hole26.hole_dia = hole26.calc_hole_size()

            hole26.show_window = "Yes"

            hole26.create()

            # hole group add end

        except: pass

 

    # define function to return web gage of column to use as default

    def ret_web_ga(mem):

        if mem.nom_depth < 9.0:

            return 3.0

        elif mem.nom_depth < 11.0:

            return 4.0

        else:

            return 6.0

    # End function definitions

    #####################################################################

    ## 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 ################################################

    while True:

        bm_list = mem_select("Select BEAM Member to Add Moment Clips", ['Beam',], ["W flange", "Tube", "Channel", "S Shape"])

        if bm_list is None:

            break

        mem1 = bm_list[0]

        #############################################################

        # Check framing conditions at ends of beam, calculate default gage in column face

        a = ColumnSupport(mem1, 2.0)

        if a.left_member <> "None":

            b = ColumnCondition(a.left_member, mem1, 2.0)

            left_end_face = b.frmg_face()

            left_col_mark = a.left_member.piecemark

            left_col_size = a.left_member.size

           

            if left_end_face == "Face B" or left_end_face == "Face D":

                col_leg_ga_left = ret_web_ga(a.left_member)

            else:

                col_leg_ga_left = a.left_member.gage

        else:

            col_leg_ga_left = col_leg_ga

            left_end_face = "None"

            left_col_mark = "None"

            left_col_size = "None"

           

        if a.right_member <> "None":

            c = ColumnCondition(a.right_member, mem1, 2.0)

            right_end_face = c.frmg_face()

            right_col_mark = a.right_member.piecemark

            right_col_size = a.right_member.size

           

            if right_end_face == "Face B" or right_end_face == "Face D":

                col_leg_ga_right = ret_web_ga(a.right_member)

            else:

                col_leg_ga_right = a.right_member.gage

        else:

            col_leg_ga_right = col_leg_ga

            right_end_face = "None"

            right_col_mark = "None"

            right_col_size = "None"

           

        # gage of beam flange for beam flange leg

        flg_ga = mem1.gage

 

        # Dialog refresh loop       

        while True:

            # Check for valid clip angle material and determine leg data

            try:

                clip_shape = Shape(clip_size)

                sh1 = Shape(clip_size)

                if llv_llh == "LLV":

                    leg_to_column = sh1.LL_depth

                    leg_to_beam = sh1.SL_depth

                else:

                    leg_to_column = sh1.SL_depth

                    leg_to_beam = sh1.LL_depth

            except:

                # If clip_size is invalid, set to known valid material

                # Default gages in the dialog box are calculated from the shape attributes

                clip_size = "L4x4x1/2"

                Warning("The default clip angle material size is invalid")

            #############################################################

            ## DIALOG BOX 1 --------------------------------------------#

            #############################################################

            dlg1 = Dialog( "Add end moment clips to a beam" )

            dlg1.menu("print_doc", ("Yes", "No"), "No", "Print documentation only                                           ")

            dlg1.tabset_begin()

            dlg1.tab("General Information")

            dlg1.group_title("Supporting Columns")

            dlg1.line("Column member at left end of beam:  %s - %s - %s" % (left_col_size,  left_col_mark, left_end_face))

            dlg1.line("Column member at right end of beam: %s - %s - %s" % (right_col_size,  right_col_mark, right_end_face))

            dlg1.group_title_end

 

            dlg1.group_title("Locations Required")

            dlg1.menu("which_end", ("Left", "Right", "Both"), which_end, "Select Which End of Beam" )

            dlg1.menu("t_or_b", ("Top", "Bott", "Both"), t_or_b, "Select Top, Bottom or Both" )

            dlg1.entry("extend_clip", extend_clip, 'Project clip beyond minus dimension')

            dlg1.group_title_end 

 

            dlg1.group_title("Clip Angle Data")

            dlg1.entry("clip_size", clip_size, "Enter material size")

            dlg1.menu("llv_llh",("LLV", "LLH"), llv_llh, "Long leg vert or horizontal?")

            dlg1.menu("steelgrade",Job().steel_grades("Angle").keys(), steelgrade, "Select material grade" )

            dlg1.menu("clip_finish", finishList, clip_finish, "Select material color" )

            dlg1.entry("edge_dist", dim_print(edge_dist), "Enter minimum edge distance at holes")

            dlg1.group_title_end

 

            dlg1.group_title("Refresh Dialog Box")

            dlg1.menu("refresh_dialog", ("Refresh", "Continue"), "Continue", "Refresh dialog box or continue")

            # dlg1.image(image_name7)

            dlg1.group_title_end           

 

            dlg1.tab("Holes/Bolts in Beam Leg")

            dlg1.group_title("Hole information in CLIP LEG against BEAM FLANGE")

            dlg1.line("If weld is selected, bolts/holes in beam flange leg will be disabled")

            dlg1.label(dim_print(leg_to_beam), "Angle leg width against BEAM")

            if add_clip_weld == 'Yes':

                add_flg_hls = 'No'

            dlg1.menu( "add_flg_hls", ("Yes", "No"), add_flg_hls, "Bolt clip to beam flange")

            dlg1.entry( "flg_ga", dim_print(flg_ga), "Enter BEAM flange gage")

            dlg1.entry( "clip_gage1", dim_print(clip_gage1), "Enter gage of CLIP LEG")

            dlg1.entry( "bolt_size1", dim_print(bolt_size1), "Enter bolt size in CLIP LEG")       

            dlg1.entry( "dbl_gage_spa1", dim_print(dbl_gage_spa1), "DBL GAGE SPACING (0 for single ga.)")

            dlg1.menu( "bolt_type_flg", Job().bolt_sched(), bolt_type_flg, "Bolt type in CLIP LEG")

            dlg1.menu( "hole_type_flg", holeTypeList, hole_type_flg, "Hole type in CLIP LEG")

            dlg1.menu( "slot_rot1", ("VT.", "HZ."), slot_rot1, "Slot rotation in CLIP LEG")

            dlg1.group_title_end 

 

            dlg1.tab("Holes/Bolts in Column Leg")

            dlg1.group_title("Supporting Columns")

            dlg1.line("Column member at left end of beam:  %s - %s - %s" % (left_col_size,  left_col_mark, left_end_face))

            dlg1.line("Column member at right end of beam: %s - %s - %s" % (right_col_size,  right_col_mark, right_end_face))

            dlg1.group_title_end

            dlg1.group_title("Hole information in CLIP LEG against COLUMN")

            dlg1.label(dim_print(leg_to_column), "Angle leg width against COLUMN")

            dlg1.entry( "col_leg_ga_left", dim_print(col_leg_ga_left), "Enter COLUMN GAGE LEFT END")

            dlg1.entry( "col_leg_ga_right", dim_print(col_leg_ga_right), "Enter COLUMN GAGE RIGHT END")

            dlg1.entry( "bolt_size", dim_print(bolt_size), "Enter bolt size in OSL")

            dlg1.entry( "clip_gage", dim_print(clip_gage), "Enter gage of OSL")

            dlg1.entry( "dbl_gage_spa", dim_print(dbl_gage_spa), "Dbl gage spa. (0 for single ga.)")

            dlg1.menu( "bolt_type_col", Job().bolt_sched(), bolt_type_col, "Bolt type in OSL")

            dlg1.menu( "hole_type_col", holeTypeList, hole_type_col, "Hole type in OSL")

            dlg1.menu( "slot_rot", ("VT.", "HZ."), slot_rot, "Slot rotation in OSL")

            dlg1.group_title_end 

 

            dlg1.tab("Weld")

            dlg1.line("If weld is selected, bolts/holes in beam flange leg will be disabled")

            dlg1.menu("add_clip_weld", ("Yes", "No"), add_clip_weld, "Add weld moment clip to beam" )

            dlg1.menu("clip_weld_type", ("Fillet", ), clip_weld_type, "Select weld type" )

            dlg1.menu("weld_size", wsList, weld_size, "Enter weld size")

 

            dlg1.tab("Illustration")

            dlg1.image(image_name1)

            dlg1.tab("Images")

            dlg1.column_group_begin()

            dlg1.column(0)

            dlg1.image(image_name2)

            dlg1.column(0)

            dlg1.image(image_name3)

            dlg1.column_group_end()

            dlg1.tabset_end()

 

            try:

                dd = dlg1.done()

            except ResponseNotOK:

                break

 

            # Update the local namespace

            for key, value in dd.items():

                exec "%s = %s" % (key, repr(value)) in None

            ###############################################################

            ## END DIALOG BOX 1 ------------------------------------------#

            ###############################################################

            if refresh_dialog == "Continue":

                break

        if print_doc == "Yes":

            print __doc__

            break

       

        try:

            clip_shape = Shape(clip_size)

        except:

            # If clip_size is invalid, set to known valid material and break out of the loop to return to member selection.

            # Default gages in the dialog box are calculated from the shape attributes

            clip_size = "L6x4x3/8"

            Warning("The clip angle material size entered is invalid - resetting to 'L6x4x3/8'")

            break               

 

        if add_clip_weld == 'Yes':

            add_flg_hls = "No"

            dd['add_flg_hls'] = "No"

 

        # Export defaults to disk if enabled

        if enable_default_import_export == "Enable":

            export_data(os.path.join(default_file_path, def_file), dd)

 

        #############################################################

        # Set slot rotations

        if slot_rot == "VT.":

            rot1 = 90.0

        else:

            rot1 = 0.0

        if slot_rot1 == "VT.":

            rot2 = 90.0

        else:

            rot2 = 0.0

 

        # Set leg orientation

        if llv_llh == "LLV":

            leg_orient = "VT."

        else:

            leg_orient = "HZ."

           

        # Set hole faces

        if leg_orient == "VT.":

            face = "Web FS"

            face1 = "Top Face"

        else:

            face = "Top Face"

            face1 = "Web FS"

 

        ## Begin beam loop

        for bm_mem in bm_list:

           

            # Calculate material work points, add clips, welds, and holes as required

            if which_end == "Right" or which_end == "Both":

                # Calculate length of clip angle

                if add_flg_hls == "Yes":

                    matl_length = max ((flg_ga + edge_dist * 2.0), (col_leg_ga_right + edge_dist * 2.0))

                else:

                    matl_length = (col_leg_ga_right + edge_dist * 2.0)

                pt10 = bm_mem.right_location

                # Calculate clip WP at member right minus dimension

                pt11 = pt10 + bm_mem.translate(-bm_mem.right.minus_dim + extend_clip, 0.0, 0.0)

                pt12 = pt11 + bm_mem.translate(0.0, 0.0, -matl_length/2.0)

                pt13 = pt12 + bm_mem.translate(0.0, 0.0, matl_length)

                pt14 = pt11 + bm_mem.translate(0.0, -(round(bm_mem.depth*16.0)/16.0), 0.0)

                pt15 = pt14 + bm_mem.translate(0.0, 0.0, -matl_length/2.0)

                pt16 = pt15 + bm_mem.translate(0.0, 0.0, matl_length)

 

                if t_or_b == "Top" or t_or_b == "Both":

               

                    rl1 = add_clip( bm_mem, pt12, pt13, clip_size, steelgrade, clip_finish, leg_orient, (-90.0, 90.0, 0.0))

                   

                    moment_clip_hole(rl1, pt11, hole_type_col, face, col_leg_ga_right/2, clip_gage,\

                                     dbl_gage_spa, rot1, bolt_type_col, bolt_size, 180.0)

                   

                    if add_flg_hls == "Yes":

                        moment_clip_hole (rl1, pt11, hole_type_flg, face1, flg_ga/2, clip_gage1,\

                                          dbl_gage_spa1, rot2, bolt_type_flg, bolt_size1, 0.0)

                       

                    if add_clip_weld == 'Yes':

                        mtrl_weld([bm_mem.main_mtrl(), ], [rl1, ], weld_size, clip_weld_type)

 

                if t_or_b == "Bott" or t_or_b == "Both":

 

                    rl2 = add_clip(bm_mem, pt16, pt15, clip_size, steelgrade, clip_finish, leg_orient, (90.0, -90.0, 0.0))

 

                    moment_clip_hole(rl2, pt14, hole_type_col, face, col_leg_ga_right/2, clip_gage,\

                                     dbl_gage_spa, rot1, bolt_type_col, bolt_size, 180.0)

                   

                    if add_flg_hls == "Yes":

                        moment_clip_hole (rl2, pt14, hole_type_flg, face1, flg_ga/2, clip_gage1,\

                                          dbl_gage_spa1, rot2, bolt_type_flg, bolt_size1, 0.0)

                       

                    if add_clip_weld == 'Yes':

                        mtrl_weld([bm_mem.main_mtrl(), ], [rl2, ], weld_size, clip_weld_type)

 

            if which_end == "Left" or which_end == "Both":

                # Calculate length of clip angle

                if add_flg_hls == "Yes":

                    matl_length = max ((flg_ga + edge_dist * 2.0), (col_leg_ga_left + edge_dist * 2.0))

                else:

                    matl_length = (col_leg_ga_left + edge_dist * 2.0)

                pt10 = bm_mem.left_location

                # Calculate clip WP at member left minus dimension

                pt11 = pt10 + bm_mem.translate(bm_mem.left.minus_dim - extend_clip, 0.0, 0.0)

                pt12 = pt11 + bm_mem.translate(0.0, 0.0, matl_length/2.0)

                pt13 = pt12 + bm_mem.translate(0.0, 0.0, -matl_length)

                pt14 = pt11 + bm_mem.translate(0.0, -(round(bm_mem.depth*16.0)/16.0), 0.0)

                pt15 = pt14 + bm_mem.translate(0.0, 0.0, matl_length/2.0)

                pt16 = pt15 + bm_mem.translate(0.0, 0.0, -matl_length)

               

                if t_or_b == "Top" or t_or_b == "Both":

                   

                    rl3 = add_clip( bm_mem, pt12, pt13, clip_size, steelgrade, clip_finish, leg_orient, (-90.0, -90.0, 0.0))

                   

                    moment_clip_hole (rl3, pt11, hole_type_col, face, col_leg_ga_left/2, clip_gage,\

                                      dbl_gage_spa, rot1, bolt_type_col, bolt_size, 180.0)

                   

                    if add_flg_hls == "Yes":

                        moment_clip_hole (rl3, pt11, hole_type_flg, face1, flg_ga/2, clip_gage1,\

                                          dbl_gage_spa1, rot2, bolt_type_flg, bolt_size1, 0.0)

                       

                    if add_clip_weld == 'Yes':

                        mtrl_weld([bm_mem.main_mtrl(), ], [rl3, ], weld_size, clip_weld_type)

                       

                if t_or_b == "Bott" or t_or_b == "Both":

                   

                    rl4 = add_clip( bm_mem, pt16, pt15, clip_size, steelgrade, clip_finish, leg_orient, (90.0, 90.0, 0.0))

                  

                    moment_clip_hole (rl4, pt14, hole_type_col, face, col_leg_ga_left/2, clip_gage,\

                                      dbl_gage_spa, rot1, bolt_type_col, bolt_size, 180.0)

                   

                    if add_flg_hls == "Yes":

                        moment_clip_hole (rl4, pt14, hole_type_flg, face1, flg_ga/2, clip_gage1,\

                                          dbl_gage_spa1, rot2, bolt_type_flg, bolt_size1, 0.0)

 

                    if add_clip_weld == 'Yes':

                        mtrl_weld([bm_mem.main_mtrl(), ], [rl4, ], weld_size, clip_weld_type)

                   

        if not yes_or_no("Add moment clips to another beam?"):

            break

## End script #######################################################

 

if __name__ == '__main__':

    try:

        run_script()

    finally:

        del run_script