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

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

##  All rights reserved.

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

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

""" Opening_Frame.py

    This script will add material to a beam member for a roof or floor opening frame.

    There is an option for the addition of saddle clips only to a beam member.

    Added frame material can be W flange, Channel, or Angle. Support for HSS material was added in R6.

    Header end condition can be saddle clips for W flange, Channel, and Angle, or stripped vertical leg for Angle.

    If saddle clips is selected, header angle material will be oriented web vertical/normal. If stripped vertical leg is selected, angle

    material for the header will be oriented flange vertical/normal. W flange, HSS and Channel material is always web vertical/normal.

    Suggested use:

        The user adds a beam and establishes the material setbacks. Ideally, the member main material should be above/left of the opening

        in plan. Since this script only adds the additional material to form the frame, the beam material entered should be the required

        frame material. Since the flange is always the short leg for beam material, user may need to rotate the member material 90 degrees

        for a stripped vertical leg on angle material. See note 10 below.

        The following instructions assume the user is in plan, and the member line is left to right or horizontal in plan:

            1. User selects a point representing the location of the left frame jamb or RETURN. A picked point will add the left jamb.

            2. User selects a point representing the location of the right frame jamb or RETURN. A picked point will add the right jamb.

            3. User selects a point representing the location of the CL of opening or RETURN. This option is available only if user selected

               RETURN for items 1 and 2. A picked point will add left and right jambs. User will be prompted for an opening length.

            4. Points selected below or on the member line will locate the opening below the member line. Points selected above the member

               line will locate the opening above the member line.

            5. If no points are selected, user will be prompted for a distance to locate the left jamb with respect to the left end WP

               location and for an opening length. Opening will always be located below the member line in this case. This option will

               add left and right jambs.

            6. User will be prompted for the opening width. The opening width is measured perpendicular to the member line.

            7. If user locates each jamb, the materials can be different. If user locates the frame center or no points are selected,

               both jambs will be the same material.

            8. Script does not check to see if jamb locations occur beyond ends of header or member main materials.

            9. Points and locations entered will locate the CL of W flange and HSS material or back of Channel and Angle material.

            10. Suggested methods for a stripped vertical leg on member material (assume member line above opening):

                a. For a long leg horizontal, enter member "Long leg" "HZ.", "Toe direction" "FS", and "cut flange flush" top flange "NS".

                b. For a long leg vertical, enter member "Long leg" "VT.", "Toe direction" "FS", and no end preparation. Rotate material

                    90 degrees. Edit material, change toe direction to "In", change long leg direction to "VT.", and "Cut flange flush"

                    NS by the required dimension each end.

                Similar methods would be used if the member line were below opening.

 

    At this time:

        The script will not add frame material to all members with the same piece mark.

        The script will always orientate angle and channel material toed away from the opening.

        The script will apply material grade "A992" for W flange material and "A36" for angle and channel material. These material grades must

        exist in job setup or the Python code must be edited.

        The script does not add welds. Weld symbols can be added with an adaptive detail.

 

    This script uses Material Fit "Frame" on the jamb material when required. Jamb material may remain if the parametric is erased. There is no

    workaround other than to manually erase the jamb material. The setbacks and end preparations do not always come out right, so the script will

    display a warning each time Material Fit "Frame" is executed.

 

    There is an annoying window that appears when adding the header angle with the stripped vertical leg end condition on angle material. Hit the OK

    button and the script will continue.

   

    This source is provided "as is."  All warranties are disclaimed.

    Developed in Python 2.2.1 - SDS/2 versions 6.331 or higher and 7.004 or higher 9/06/04 (R1)

 

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

    For comments, suggestions or questions call BVD at the number above or email bvaughan@bvdetailing.com.

 

    R2 -    (9/21/04) Fixed condition where frame is expected to be placed below the member line but is placed above the member line

            by rounding the local point "z" value.

 

    R3 -    This script did not work properly when framing to a joist member. SDS/2 returns a dihedral of 0.0, which blows up the script. Code was

            added to account for this problem. Code was added to test for a dihedral between 10 and -10 degrees and then read mem.left.flange_cut_angle

            or mem.right.flange_cut_angle. The existing member must be processed for the actual framing condition. Copied members with user ends will

            get unexpected results.

    R4 -    Added condional statement. Script would bomb if "Case_No" was not defined. "Case_No" is not required when script_action = saddle_clips.

            Added code to calculate correct saddle clip location for header angle with long leg horizontal.

            Added ClearSelection()

    R5 -    Fix what R4 messed up.

    R6 -    Added support for HSS beam material.

    R7 -    Fixed a problem with angle member material, long leg vertical. Search for "Release 7 added 3 lines"

    R8 -    Account for angle member material with equal legs or long leg horizontal in function end_angles

            Use dd.file for selection of default file names

           

    Version 1.00 (4/8/07) - Drop support for SDS/2 version 6.3

                            Auto import/export defaults values file

                            Improve user defaults values file import/export

                            Consolidate dialog box

    Version 1.01 (10/21/07) - Discontinue import_user_data, export_user_data

                              Move imports outside of run_script

                              Add ClearSelection() in try/finally block

                              Add dim_print several places in dialog box

"""

 

# startup code begin

import macrolib.pickle

from macrolib.FileDefaults import import_data, export_data, job_Defaults_path1, check_Defaults_dir

from macrolib.angle import rtod, dtor

from macrolib.ExceptWarn import formatExceptionInfo

from macrolib.MemSelection import mem_select

from macrolib.angle import rtod, dtor

from macrolib.Weld import mtrl_weld

 

import os

import sys

 

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

from math import pi, cos, sin, tan, sqrt

Units("feet")

 

from job import Job

from fab import Fabricator

from shape import Shape

from point import Point, PointLocate

from member import Member, MemberLocate

from rolled_section import RolledSection

# startup code end

 

def run_script():

    ## Variables section

    # system path for defaults file

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

    # auto defaults file

    autoDef_file = "Opening_Frame_v1_00.txt"

    # default to enable or disable the importing and exporting of dialog dictionary variables

    # ("Enable", "Disable") to/from 'autoDef_file'

    enable_default_import_export = "Enable"

 

    # check if automatic defaults directory exists

    if enable_default_import_export == "Enable":

        if not check_Defaults_dir(default_file_path):

            Warning("Auto default values file save/read will not work.")

           

    # Dialog box image path and file name

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

 

    script_name = "Opening_Frame"

 

    # Dialog box image path and file name

    image_name = os.path.join(image_path, "Opening_Frame.gif")

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

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

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

    image_name4 = os.path.join(image_path, "Opening_Frame4.gif")

 

    # user defaults file

    default_file_for_saving_path = job_Defaults_path1()

    default_file_for_saving = os.path.join(default_file_for_saving_path, "OpngFrame.txt")

    default_file_for_importing = os.path.join(default_file_for_saving_path, "*.txt")

    # ("Yes", "No")

    default_save = "No"

 

    # check if user defaults directory exists

    if not check_Defaults_dir(default_file_for_saving_path):

        default_file_for_saving_path = default_file_path

 

    finishList = ["None", "Red Oxide", "Yellow Zinc", "Gray Oxide", "Sandblasted", "Blued Steel", "Galvanized"]   

 

    ## Defaults section

    script_options = 'Add Opening'

    header_mtrl = "L4x4x1/4"

    header_orient = "LLV"                   # ("LLV", "LLH")

    header_end_condition = "Saddle Clip"    # ("Saddle Clip", "Strip Vert Leg")

    strip_left_length = 3.0

    strip_right_length = 3.0

    jamb_left_mtrl = "L4x4x1/4"

    jamb_left_orient = "LLV"                # ("LLV", "LLH")

    jamb_left_location = 18.0               # Location of left jamb with respect to member.left_location

    jamb_right_mtrl = "L4x4x1/4"

    jamb_right_orient = "LLV"               # ("LLV", "LLH")

    frame_color = "Gray Oxide"              # "Red Oxide", "Yellow Zinc", "Gray Oxide", "Sandblasted", "Blued Steel", "Galvanized"

    opening_length = 38.0                   # Length of opening is measured parallel to member line

    opening_width = 38.0                    # Width of opening is measured perpendicular to member line

    saddle_mtrl = "L5x5x5/16"

    saddle_length = 4.0

    saddle_orient = "LLV"                   # ("LLV", "LLH")

    saddle_color = "Yellow Zinc"            # "Red Oxide", "Yellow Zinc", "Gray Oxide", "Sandblasted", "Blued Steel", "Galvanized"

 

    add_weld = 'Yes'

    # ['1/8', '3/16', '1/4']

    weld_size = '3/16'

    weld_type = 'Fillet'

 

    ## End defaults section

    ## Begin Function Definition Section

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

    # Define function to add a rolled shape material for saddle clip end condition

    def apply_rolled_matl (mem, pt1, pt2, matl_size, orientate, toe_dir, matl_color, \

                           matl_grade, flg_cut_left, flg_cut_right, rot_arg):

       

        if orientate == "LLV":

            leg_orient = "HZ."

        else:

            leg_orient = "VT."

        matl_type = Shape(matl_size).type()

        # rolled section begin

        rl1 = RolledSection()

        rl1.member = mem

        rl1.pt1 = pt1

        rl1.pt2 = pt2

        rl1.section_size = matl_size

        rl1.grade = matl_grade

        rl1.centered = "No"

        rl1.top_oper_left = "None"

        rl1.top_length_left = 0.0

        rl1.top_cope_left = 0.0  

        rl1.top_oper_right = "None"

        rl1.bottom_oper_left = "None"

        rl1.bottom_length_left = 0.0

        rl1.bottom_cope_left = 0.0

        rl1.bottom_oper_right = "None"

        rl1.llv = leg_orient

        rl1.toe_io = toe_dir

        rl1.rolling_op = "None"

        rl1.width = 0

        rl1.thick = 0

        rl1.field_weld_prep_left = "No"

        rl1.field_weld_prep_right = "No"

        rl1.cut_radius_left = 0.5

        rl1.cut_radius_right = 0.5

        rl1.work_pt_dist = pt1.dist(pt2)

        rl1.setback_left = 0.0

        rl1.setback_right = 0.0

        rl1.web_cut_angle_left = 0

        rl1.web_cut_angle_right = 0

        rl1.flange_cut_left = flg_cut_left

        rl1.flange_cut_right = flg_cut_right

        rl1.end_cut_left = "Standard Cut"

        rl1.end_cut_right = "Standard Cut"

        rl1.length = rl1.work_pt_dist - rl1.setback_left - rl1.setback_right

        rl1.mtrl_type = matl_type

        rl1.finish = matl_color

        rl1.ref_pt_offset = (0.000000, 0.000000, 0.000000)

        rl1.add()

        rl1.rotate(rl1.member, rot_arg)

        # rolled section end

        return rl1

    # End function definition

 

    # Define function to add a rolled shape material for strip vertical legp end condition

    def apply_rolled_matl_strip (mem, pt1, pt2, matl_size, orientate, toe_dir, matl_color, \

                                 matl_grade, flg_cut_left, flg_cut_right, rot_arg):

       

        if orientate == "LLV":

            leg_orient = "VT."

        else:

            leg_orient = "HZ."

        if toe_dir == "In":

            flg_cut_left_NS = flg_cut_left

            flg_cut_left_FS = 0.0

            flg_cut_right_NS = flg_cut_right

            flg_cut_right_FS = 0.0

        else:

            flg_cut_left_FS = flg_cut_left

            flg_cut_left_NS = 0.0

            flg_cut_right_FS = flg_cut_right

            flg_cut_right_NS = 0.0

        matl_type = Shape(matl_size).type()

       

        # rolled section begin

        rl1 = RolledSection()

        rl1.member = mem

        rl1.pt1 = pt1

        rl1.pt2 = pt2

        rl1.section_size = matl_size

        rl1.grade = matl_grade

        rl1.centered = "No"

        rl1.top_oper_left = "Cut flange flush"

        rl1.top_oper_right = "Cut flange flush"

        rl1.top_length_NS_left = flg_cut_left_NS

        rl1.top_length_NS_right = flg_cut_right_NS

        rl1.top_length_FS_left = flg_cut_left_FS

        rl1.top_length_FS_right = flg_cut_right_FS

        rl1.bottom_oper_left = "None"

        rl1.bottom_oper_right = "None"

        rl1.llv = leg_orient

        rl1.toe_io = toe_dir

        rl1.rolling_op = "None"

        rl1.width = 0

        rl1.thick = 0

        rl1.field_weld_prep_left = "No"

        rl1.field_weld_prep_right = "No"

        rl1.cut_radius_left = 0.5

        rl1.cut_radius_right = 0.5

        rl1.work_pt_dist = pt1.dist(pt2)

        rl1.setback_left = 0.0

        rl1.setback_right = 0.0

        rl1.web_cut_angle_left = 0

        rl1.web_cut_angle_right = 0

        rl1.flange_cut_left = 0

        rl1.flange_cut_right = 0

        rl1.end_cut_left = "Standard Cut"

        rl1.end_cut_right = "Standard Cut"

        rl1.length = rl1.work_pt_dist - rl1.setback_left - rl1.setback_right

        rl1.mtrl_type = matl_type

        rl1.finish = matl_color

        rl1.ref_pt_offset = (0.000000, 0.000000, 0.000000)

        rl1.add()

        rl1.rotate(rl1.member, rot_arg)

        # rolled section end

        return rl1

    # End function definition

 

    # Define function to determine end conditions of existing member

    def end_angles (mem):

        if mem.left.dihedral < 10.0 and mem.left.dihedral > -10.0:

            ang_left_cut = mem.left.flange_cut_angle

            if mem.left.flange_cut_angle <= 0.0:

                ang_left = mem.left.flange_cut_angle + 90.0

            else:

                ang_left = mem.left.flange_cut_angle - 90.0

            if mem1.mtrl_type == "Angle":

                if mem.SL_depth == mem.LL_depth or mem.LLV == "HZ.":

                    ang_left_cut = -mem.left.web_cut_angle

                    if mem.left.web_cut_angle <= 0.0:

                        ang_left = -mem.left.web_cut_angle + 90.0

                    else:

                        ang_left = -mem.left.web_cut_angle - 90.0       

        else:     

            ang_left = mem.left.dihedral

            ang_left_cut = 90.0 + mem1.left.dihedral

            if ang_left_cut > 90.0:

                ang_left_cut = ang_left_cut - 180.0

        if ang_left < 0.0:

            ang_left = ang_left + 180.0

        if mem.right.dihedral < 10.0 and mem.right.dihedral > -10.0:

            ang_right_cut = mem.right.flange_cut_angle

            if mem.right.flange_cut_angle <= 0.0:

                ang_right = mem.right.flange_cut_angle + 90.0

            else:

                ang_right = mem.right.flange_cut_angle - 90.0

            if mem1.mtrl_type == "Angle":

                if mem.SL_depth == mem.LL_depth or mem.LLV == "HZ.":

                    ang_right_cut = -mem.right.web_cut_angle

                    if mem.right.web_cut_angle <= 0.0:

                        ang_right = -mem.right.web_cut_angle + 90.0

                    else:

                        ang_right = -mem.right.web_cut_angle - 90.0

        else:       

            ang_right = mem1.right.dihedral

            ang_right_cut = 90.0 + mem1.right.dihedral

            if ang_right_cut > 90.0:

                ang_right_cut = ang_right_cut - 180.0

        if ang_right > 0.0:

            ang_right = ang_right + 180.0

        return (ang_left, ang_right, ang_left_cut, ang_right_cut)

    # End function definition

 

    # Define function to fit material "Frame"

    def fit_mtrl_frame(rl9, mtrl9):

        try:

            # mtrl fit begin

            mfit1 = MtrlFit()

            mfit1.mtrl = [rl9, ]

            mfit1.to = [mtrl9, ]

            mfit1.frame_type = "Plain"

            mfit1.cut_clear = 0

            mfit1.end_clear = 0

            mfit1.show_window = "No"

            mfit1.fit("Frame")

            # mtrl fit end

        except:

            pass

    ## End function definitions

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

    # Import autoDef_file if enabled

    if enable_default_import_export == "Enable":

        dd = import_data(os.path.join(default_file_path, autoDef_file))

        if dd:

            for key, value in dd.items():

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

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

    try:

        ## Main program loop ######################################################

        while True:

            ClearSelection()

 

            outDict = {}   

 

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

            ## DIALOG BOX 0 #######################################################

            dlg0 = Dialog("Roof Opening Frame")

            dlg0.menu("script_options", ("Print Documentation", "Add Opening", "Saddle Clips", "Quit"), script_options, "Select action")

            dlg0.group_title('Defaults file import')

            dlg0.menu("import_user_defaults", ('Yes', 'No'), 'No', 'Import user default file?')

            dlg0.file('import_fn', default_file_for_importing, "Enter file name to import")

            dlg0.group_title_end

            try:

                dd0 = dlg0.done()

            except ResponseNotOK:

                break

            for key, value in dd0.items():

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

 

            outDict.update(dd0)

 

            if script_options == "Quit":

                break

            elif script_options == 'Print Documentation':

                print __doc__

                break       

 

            script_action = script_options

           

            if import_user_defaults == 'Yes':

                dd = import_data(import_fn)

                if dd:

                    for key, value in dd.items():

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

                        except: Warning("User import failed")

 

            # Select beam member

            bm_list = mem_select("Select a BEAM member to add %s." % script_action, ['Beam',], ["W flange", "Angle", "Channel", "Tube"], True, False)   

            if len(bm_list) < 1:

                break

            mem1 = bm_list[0]

           

            ## Select points or return. If point(s) is selected above the member line, the opening will be located accordingly.

            if script_action == "Add Opening":

                which_side = "Below"

                pt21 = PointLocate("Select LEFT JAMB location or RETURN")

                if pt21:

                    pt21_local = mem1.trans_to_local(pt21 - mem1.left_location)

                else: pt21_local = None

               

                pt22 = PointLocate("Select RIGHT JAMB location or RETURN")

                if pt22:

                    pt22_local = mem1.trans_to_local(pt22 - mem1.left_location)

                else: pt22_local = None

                

                if pt21_local == None and pt22_local == None:

                    pt23 = PointLocate("Select OPENING CENTER location or RETURN")

                    if pt23:

                        pt23_local = mem1.trans_to_local(pt23 - mem1.left_location)

                    else: pt23_local = None

                else:

                    pt23_local = None

                    if pt21_local <> None:

                        if round(pt21_local.z, 2) < 0.0:

                            which_side = "Above"

                    if pt22_local <> None:

                        if round(pt22_local.z, 2) < 0.0:

                            which_side = "Above"

                           

                if pt23_local <> None:

                    if round(pt23_local.z, 2) < 0.0:

                        which_side = "Above"

 

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

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

            if script_action == "Add Opening":

                dlg1 = Dialog("Add opening material to a beam member")

                dlg1.menu("default_save", ("Yes", "No"), "No", "Save all script defaults to a disk file?")

                dlg1.file_save('export_file', default_file_for_saving, "Enter file name")

               

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

 

                dlg1.tabset_begin()    

                dlg1.tab("General Information")

 

                dlg1.line("Selected member is a " + mem1.size + " at left end location " + dim_print(mem1.left_location.x) + " , " +\

                          dim_print(mem1.left_location.y) + " , " + dim_print(mem1.left_location.z))

               

                dlg1.group_title("Opening Frame Dimensional Information" )

                if pt21_local <> None and pt22_local <> None:

                    Case_No = "Case A"

                    opening_length = pt22_local.x - pt21_local.x

                    jamb_left_dim = pt21_local.x

                    jamb_right_dim = jamb_left_dim + opening_length

                    dlg1.label(dim_print(jamb_left_dim), "User selected LEFT JAMB location with respect to left end WP:    ")

                    dlg1.label(dim_print(opening_length), "User selected opening length - parallel to member line:    ")

                    dlg1.entry("opening_width", dim_print(opening_width), "Enter opening WIDTH - perpendicular to member line")

                elif pt21_local <> None:

                    Case_No = "Case B"

                    jamb_left_dim = pt21_local.x

                    jamb_right_dim = None

                    dlg1.label(dim_print(jamb_left_dim), "User selected LEFT JAMB location with respect to left end WP:    ")

                    dlg1.entry("opening_width", dim_print(opening_width), "Enter opening WIDTH - perpendicular to member line")

                elif pt22_local <> None:

                    Case_No = "Case C"

                    jamb_right_dim = pt22_local.x

                    jamb_left_dim = None

                    dlg1.label(dim_print(jamb_right_dim), "User selected RIGHT JAMB location with respect to left end WP:    ")

                    dlg1.entry("opening_width", dim_print(opening_width), "Enter opening WIDTH - perpendicular to member line")

                elif pt23_local <> None:

                    Case_No = "Case D"

                    dlg1.label(dim_print(pt23_local.x), "User selected OPENING CENTER location with respect to left end WP:    ")

                    dlg1.entry("opening_length", dim_print(opening_length), "Enter opening LENGTH - parallel to member line        ")

                    dlg1.entry("opening_width", dim_print(opening_width), "Enter opening WIDTH - perpendicular to member line    ")

                else:

                    Case_No = "Case E"

                    dlg1.entry("jamb_left_location", jamb_left_location, "Enter LEFT JAMB location with respect to left end WP                ")

                    dlg1.entry("opening_length", dim_print(opening_length), "Enter opening LENGTH - parallel to member line")

                    dlg1.entry("opening_width", dim_print(opening_width), "Enter opening WIDTH - perpendicular to member line")

                dlg1.image(image_name2)

 

                dlg1.tab('Header and Jamb')

                dlg1.group_title("Frame HEADER Information" )

                dlg1.line("Strip Vert Leg header end support condition applies to Angle material only")

                dlg1.entry("header_mtrl", header_mtrl, "Header material size - WF, Channel, or Angle")

                dlg1.menu("header_end_condition", ("Saddle Clip", "Strip Vert Leg"), header_end_condition, "Header end support condition")

                dlg1.menu("header_orient",("LLV", "LLH") , header_orient, "Header material orientation (applies to ANGLE material)")

                dlg1.menu("frame_color", finishList, frame_color, "Frame Material finish")

               

                if Case_No == "Case A" or Case_No == "Case B":

                    dlg1.group_title("LEFT JAMB information")

                    dlg1.entry("jamb_left_mtrl", jamb_left_mtrl, "LEFT JAMB material size")

                    dlg1.menu("jamb_left_orient", ("LLV", "LLH"), jamb_left_orient, "LEFT JAMB material orientation (applies to ANGLE material)")

                if Case_No == "Case A" or Case_No == "Case C":

                    dlg1.group_title("RIGHT JAMB information")

                    dlg1.entry("jamb_right_mtrl", jamb_right_mtrl, "RIGHT JAMB material size")

                    dlg1.menu("jamb_right_orient", ("LLV", "LLH"), jamb_right_orient, "RIGHT JAMB material orientation (applies to ANGLE material)")

                if Case_No == "Case D" or Case_No == "Case E":

                    dlg1.group_title("JAMB information")

                    dlg1.entry("jamb_left_mtrl", jamb_left_mtrl, "JAMB material size")

                    dlg1.menu("jamb_left_orient", ("LLV", "LLH"), jamb_left_orient, "JAMB material orientation (applies to ANGLE material)")

 

                dlg1.tab("Saddle Clip Information")

                dlg1.line("Selected member is a " + mem1.size + " at left end location " + dim_print(mem1.left_location.x) + " , "\

                          + dim_print(mem1.left_location.y) + " , " + dim_print(mem1.left_location.z))

                dlg1.entry("saddle_mtrl", saddle_mtrl, "Saddle clip material size       ")

                dlg1.entry("saddle_length", dim_print(saddle_length), "Saddle clip material length     ")

                dlg1.menu("saddle_orient", ("LLV", "LLH"), saddle_orient, "Saddle clip material orientation")

                dlg1.menu("saddle_color", ("Red Oxide", "Yellow Zinc", "Gray Oxide", "Sandblasted", "Blued Steel", "Galvanized"),\

                          saddle_color, "Saddle clip material color")

                dlg1.image(image_name4)

 

                dlg1.tab('Strip Vertical Leg Dims')

                dlg1.entry("strip_left_length", strip_left_length, "Left end length of strip")

                dlg1.entry("strip_right_length", strip_right_length, "Right end length of strip")

               

                dlg1.tab("Weld")

                dlg1.menu("add_weld", ("Yes", "No"), add_weld, "Add weld to frame/header" )

                dlg1.menu("weld_type", ("Fillet", ), weld_type, "Weld type" )

                dlg1.menu("weld_size", ['1/8', '3/16', '1/4'], dim_print(weld_size), "Weld size")               

                   

                dlg1.tab("Image")

                dlg1.image(image_name)

                dlg1.tabset_end()

 

            elif script_action == 'Saddle Clips':

                dlg1 = Dialog("Add saddle clips to a beam member")

                dlg1.menu("default_save", ("Yes", "No"), "No", "Save all script defaults to a disk file?")

                dlg1.file('export_file', default_file_for_saving, "Enter file name")

               

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

 

                dlg1.tabset_begin()    

                dlg1.tab("General Information")

               

                dlg1.line("Selected member is a " + mem1.size + " at left end location " + dim_print(mem1.left_location.x) + " , "\

                          + dim_print(mem1.left_location.y) + " , " + dim_print(mem1.left_location.z))

                dlg1.group_title("Saddle clip angle information")

                dlg1.entry("saddle_mtrl", saddle_mtrl, "Saddle clip material size       ")

                dlg1.entry("saddle_length", dim_print(saddle_length), "Saddle clip material length     ")

                dlg1.menu("saddle_orient", ("LLV", "LLH"), saddle_orient, "Saddle clip material orientation")

                dlg1.menu("saddle_color", finishList, saddle_color, "Saddle clip material finish")

                dlg1.image(image_name3)

 

                dlg1.tab("Weld")

                dlg1.menu("add_weld", ("Yes", "No"), add_weld, "Add weld to frame/header" )

                dlg1.menu("weld_type", ("Fillet", ), weld_type, "Weld type" )

                dlg1.menu("weld_size", ['1/8', '3/16', '1/4'], dim_print(weld_size), "Weld size")               

                   

                dlg1.tab("Image")

                dlg1.image(image_name)

                dlg1.tabset_end()

                   

            try:

                dd1 = dlg1.done()

            except ResponseNotOK:

                break

           

            for key, value in dd1.items():

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

 

            outDict.update(dd1)

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

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

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

 

            if print_doc == "Yes":

                print __doc__

                break   

               

            if default_save == "Yes":

                if not export_data(export_file, outDict, script_name):

                    Warning("Error exporting default data")

 

            # Export defaults to disk if enabled

            if enable_default_import_export == "Enable":

                export_data(os.path.join(default_file_path, autoDef_file), outDict)        

 

            # Calculate jamb locations if selection Case No is "D" or "E"

            if script_action == "Add Opening":

                if Case_No == "Case D":

                    jamb_left_dim = pt23_local.x - opening_length/2

                    jamb_right_dim = pt23_local.x + opening_length/2

                    jamb_right_mtrl = jamb_left_mtrl

                    jamb_right_orient = jamb_left_orient

                if Case_No == "Case E":

                    jamb_left_dim = jamb_left_location

                    jamb_right_dim = jamb_left_location + opening_length

                    jamb_right_mtrl = jamb_left_mtrl

                    jamb_right_orient = jamb_left_orient

            if Shape(header_mtrl).type() in ("W flange", "Channel", "Tube"):

                header_end_condition = "Saddle Clip"

               

            # Determine end conditions of existing member

            left_angle, right_angle, cut_left_angle, cut_right_angle = end_angles (mem1)

 

            # frame material list for welding

            frameList = [mem1.main_mtrl(),]   

 

            ## Add saddle clips - Saddle clip material is A36

            if script_action == "Saddle Clips" or (script_action == "Add Opening" and header_end_condition == "Saddle Clip"):

                if mem1.mtrl_type in ("W flange", "Tube"):

                    offset_dist_left = saddle_length / 2

                    offset_dist_right = saddle_length / 2

                elif mem1.mtrl_type == "Angle" and mem1.SL_depth != mem1.LL_depth:

                    if mem1.LLV == "HZ.":

                        offset_dist_left = max(0.0, (saddle_length - (round (mem1.depth / abs(sin(dtor(left_angle))) * 4.0) / 4.0)) / 2)

                        offset_dist_right = max(0.0, (saddle_length - (round (mem1.depth / abs(sin(dtor(right_angle))) * 4.0) / 4.0)) / 2)

                    else:

                        offset_dist_left = max(0.0, (saddle_length - (round (mem1.bf / abs(sin(dtor(left_angle))) * 4.0) / 4.0)) / 2)

                        offset_dist_right = max(0.0, (saddle_length - (round (mem1.bf / abs(sin(dtor(right_angle))) * 4.0) / 4.0)) / 2)

                else:

                    offset_dist_left = max(0.0, (saddle_length - (round (mem1.bf / abs(sin(dtor(left_angle))) * 4.0) / 4.0)) / 2)

                    offset_dist_right = max(0.0, (saddle_length - (round (mem1.bf / abs(sin(dtor(right_angle))) * 4.0) / 4.0)) / 2)

                   

                if mem1.toeio == "Out":

                    pt11 = mem1.left_location + mem1.translate(mem1.left.setback - cos(dtor(left_angle)) * offset_dist_left, \

                                                           Shape(saddle_mtrl).thick, sin(dtor(left_angle)) * offset_dist_left)

                    pt12 = mem1.right_location + mem1.translate(-mem1.right.setback - cos(dtor(right_angle)) * (saddle_length - offset_dist_right), \

                                                           Shape(saddle_mtrl).thick, sin(dtor(right_angle)) * (saddle_length - offset_dist_right))

                else:

                    pt11 = mem1.left_location + mem1.translate(mem1.left.setback - cos(dtor(left_angle)) * (saddle_length - offset_dist_left), \

                                                           Shape(saddle_mtrl).thick, sin(dtor(left_angle)) * (saddle_length - offset_dist_left))

                    pt12 = mem1.right_location + mem1.translate(-mem1.right.setback - cos(dtor(right_angle)) * offset_dist_right, \

                                                           Shape(saddle_mtrl).thick, sin(dtor(right_angle)) * offset_dist_right)

               

                rl11 = apply_rolled_matl (mem1, pt11, pt11 + mem1.translate(saddle_length, 0.0, 0.0), saddle_mtrl, saddle_orient, "Out", saddle_color,\

                                          "A36", 0.0, 0.0, (0.0, -left_angle, 0.0))

                rl12 = apply_rolled_matl (mem1, pt12, pt12 + mem1.translate(saddle_length, 0.0, 0.0), saddle_mtrl, saddle_orient, "Out", saddle_color,\

                                          "A36", 0.0, 0.0, (0.0, -right_angle, 0.0))

                if add_weld == 'Yes':

                    for m in [rl11, rl12]:

                        mtrl_weld(frameList, [m, ], weld_size, weld_type)

               

            if script_action == "Add Opening":

                # Add opposite header material with saddle clips

                # W flange is added as A992 material

                # Channel and Angles are added as A36 material

                if header_end_condition == "Saddle Clip":

                    if Shape(header_mtrl).type() == "W flange":

                        offset_dist_left = saddle_length / 2

                        offset_dist_right = saddle_length / 2

                        mtrl_grade = "A992"

                    elif Shape(header_mtrl).type() == "Tube":

                        offset_dist_left = saddle_length / 2

                        offset_dist_right = saddle_length / 2

                        mtrl_grade = "A500B"

                    else:       

                        offset_dist_left = max(0.0, (saddle_length - (round (Shape(header_mtrl).bf / abs(sin(dtor(left_angle))) * 4.0) / 4.0)) / 2)

                        offset_dist_right = max(0.0, (saddle_length - (round (Shape(header_mtrl).bf / abs(sin(dtor(right_angle))) * 4.0) / 4.0)) / 2)

                        mtrl_grade = "A36"

                       

                    if which_side == "Above":

                        pt13 = mem1.left_location + mem1.translate(mem1.left.setback - tan(dtor(cut_left_angle)) * opening_width, 0.0, -opening_width)

                        pt13a = mem1.right_location + mem1.translate(-mem1.right.setback - tan(dtor(cut_right_angle)) * opening_width, 0.0, -opening_width)

                        rl13 = apply_rolled_matl (mem1, pt13, pt13a, header_mtrl, header_orient, "Out", frame_color,\

                                                  mtrl_grade, cut_left_angle, cut_right_angle, (0.0, 0.0, 0.0))

                        pt13b = pt13 + mem1.translate(-cos(dtor(left_angle)) * offset_dist_left, Shape(saddle_mtrl).thick, sin(dtor(left_angle)) * offset_dist_left)

                        pt13c = pt13a + mem1.translate(-cos(dtor(right_angle)) * (saddle_length - offset_dist_right), Shape(saddle_mtrl).thick,\

                                                       sin(dtor(right_angle)) * (saddle_length - offset_dist_right))

                    else:

                        pt13 = mem1.left_location + mem1.translate(mem1.left.setback + tan(dtor(cut_left_angle)) * opening_width, 0.0, opening_width)

                        pt13a = mem1.right_location + mem1.translate(-mem1.right.setback + tan(dtor(cut_right_angle)) * opening_width, 0.0, opening_width)

                        rl13 = apply_rolled_matl (mem1, pt13, pt13a, header_mtrl, header_orient, "In", frame_color,\

                                                  mtrl_grade, cut_left_angle, cut_right_angle, (0.0, 0.0, 0.0))

                        pt13b = pt13 + mem1.translate(-cos(dtor(left_angle)) * (saddle_length - offset_dist_left), Shape(saddle_mtrl).thick,\

                                                      sin(dtor(left_angle)) * (saddle_length - offset_dist_left))

                        pt13c = pt13a + mem1.translate(-cos(dtor(right_angle)) * offset_dist_right, Shape(saddle_mtrl).thick, sin(dtor(right_angle)) * offset_dist_right)

 

                    frameList.append(rl13)

                   

                    rl13b = apply_rolled_matl (mem1, pt13b, pt13b + mem1.translate(saddle_length, 0.0, 0.0), saddle_mtrl, saddle_orient, "Out", saddle_color,\

                                              "A36", 0.0, 0.0, (0.0, -left_angle, 0.0))

                    rl13c = apply_rolled_matl (mem1, pt13c, pt13c + mem1.translate(saddle_length, 0.0, 0.0), saddle_mtrl, saddle_orient, "Out", saddle_color,\

                                              "A36", 0.0, 0.0, (0.0, -right_angle, 0.0))

                    if add_weld == 'Yes':

                        for m in [rl13b, rl13c]:

                            mtrl_weld(frameList, [m, ], weld_size, weld_type)

                   

                # Add opposite header material with stripped vertical leg - Angle material only, added as A36 material

                elif header_end_condition == "Strip Vert Leg":

                    if which_side == "Above":

                        pt13 = mem1.left_location + mem1.translate(mem1.left.setback - tan(dtor(cut_left_angle)) * opening_width, 0.0, -opening_width)

                        pt13a = mem1.right_location + mem1.translate(-mem1.right.setback - tan(dtor(cut_right_angle)) * opening_width, 0.0, -opening_width)

                        rl13 = apply_rolled_matl_strip (mem1, pt13, pt13a, header_mtrl, header_orient, "In", frame_color,\

                                                            "A36", strip_left_length, strip_right_length, (90.0, 0.0, 0.0))

                    else:

                        pt13 = mem1.left_location + mem1.translate(mem1.left.setback + tan(dtor(cut_left_angle)) * opening_width, 0.0, opening_width)

                        pt13a = mem1.right_location + mem1.translate(-mem1.right.setback + tan(dtor(cut_right_angle)) * opening_width, 0.0, opening_width)

                        rl13 = apply_rolled_matl_strip (mem1, pt13, pt13a, header_mtrl, header_orient, "Out", frame_color,\

                                                        "A36", strip_left_length, strip_right_length, (-90.0, 0.0, 0.0))

                       

                    frameList.append(rl13)

                       

                # Add jamb material

                if jamb_left_dim:

                    if which_side == "Above":

                        pt14 = mem1.left_location + mem1.translate(jamb_left_dim, 0.0, 0.0)

                    else:

                        pt14 = mem1.left_location + mem1.translate(jamb_left_dim, 0.0, opening_width)

                       

                    pt14a = pt14 + mem1.translate(opening_width, 0.0, 0.0)

                    rot_arg = (0.0, -90.0, 0.0)

                    

                    rl14 = apply_rolled_matl (mem1, pt14, pt14a, jamb_left_mtrl, jamb_left_orient, "Out", frame_color, "A36", 0.0, 0.0, rot_arg)

                   

                    if add_weld == 'Yes':

                        mtrl_weld(frameList, [rl14, ], weld_size, weld_type)

                   

                    if mem1.mtrl_type in ("W flange", "Tube") or (which_side == "Above" and mem1.toeio == "Out") or (which_side == "Below" and mem1.toeio == "In"):

                        fit_mtrl_frame(rl14, mem1)

                        Warning("Jamb material was fitted to member material. Check preparation.")

                       

                    if Shape(header_mtrl).type() in ("W flange", "Tube"):

                        fit_mtrl_frame(rl14, rl13)

                        Warning("Jamb material was fitted to header material. Check preparation.")

                       

                if jamb_right_dim:

                    if which_side == "Above":

                        pt15 = mem1.left_location + mem1.translate(jamb_right_dim, 0.0, -opening_width)

                    else:

                        pt15 = mem1.left_location + mem1.translate(jamb_right_dim, 0.0, 0.0)

                       

                    pt15a = pt15 + mem1.translate(opening_width, 0.0, 0.0)

                    rot_arg = (0.0, 90.0, 0.0)

                   

                    rl15 = apply_rolled_matl (mem1, pt15, pt15a, jamb_right_mtrl, jamb_right_orient, "Out", frame_color, "A36", 0.0, 0.0, rot_arg)

 

                    if add_weld == 'Yes':

                        mtrl_weld(frameList, [rl15, ], weld_size, weld_type)           

                   

                    if Shape(header_mtrl).type() in ("W flange", "Tube"):

                        fit_mtrl_frame(rl15, rl13)

                        Warning("Jamb material was fitted to header material. Check preparation.")

                       

                    if mem1.mtrl_type in ("W flange", "Tube") or (which_side == "Above" and mem1.toeio == "Out") or (which_side == "Below" and mem1.toeio == "In"):

                        fit_mtrl_frame(rl15, mem1)

                        Warning("Jamb material was fitted to member material. Check preparation.")

                       

            if not yes_or_no('Add another?'):

                break

    except:

        Warning(formatExceptionInfo())

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

 

if __name__ == '__main__':

    try:

        run_script()

    finally:

        ClearSelection()

        del run_script