##  Col_SafetyTabs Version 1.03

##  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 safety cable tabs to WF, Pipe, or Tube columns.

    Select columns to add tabs to and beams or joists to establish reference points.

    A dialog box will come up for each column selected. The script will attempt to add a tab

    for each beam selected to the columns using the values set in the dialog box. If the tabs fall off

    the column or if the script attempts to add a tab where one exists, the script will not error.

    The tab hole will be placed in the center of the tab plate.

    The tab plates will be located on the CL of the column.

   

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

 

    An option to add the same tab plates to all members with the same mark has not been implemented in this script.

 

    Revision History:

    Version 1.02 (10/30/06) -   Import modules

                                Use 'os.getcwd()' to determine the current working directory.

                                The current working directory should be the SDS/2 data root directory.

                                Create function to run script - all variables are local - delete from

                                    global namespace upon exit

                                Add option in dialog box to print documentation only

                                Add weld

    Version 1.03 (11/27/06) -   Eliminate imports string and types

 

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

    Developed in SDS/2 7.023, Python 2.2.1, 3/21/06 (Version 1.01)

 

    ************************************************************

    ****NOTE: This version is not compatible with SDS/2 6.3.****

    ************************************************************   

 

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

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

    bvaughan@bvdetailing.com or post to forum.

    Credit Phil Adams [padams@colloquiuminc.com] for function "formatExceptionInfo()"

 

    NOT FOR SALE

 

    Go to 'Variables section' to turn off the importing and exporting of the default values file

    Go to 'Variables section' to edit system paths for image and default files

    Go to 'Defaults section' to edit script default values.

 

    Required files from folder 'macrolib' on SDS/2 system path:

        pickle.py (required for FileDefaults)

        FileDefaults.py

        angle.py

        ExceptWarn.py

        L3D.py

        Weld.py

 

    Required folders:

        "system path"/macrolib

        "system path"/Defaults

        "system path"/Images

 

"""

# startup code begin

# from math import cos, sin, atan2, ceil

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

from member import Member, MemberLocate

from point import Point, PointLocate

import macrolib.pickle

from macrolib.FileDefaults import import_data, export_data

from macrolib.angle import rtod, dtor

from macrolib.ExceptWarn import formatExceptionInfo

from macrolib.L3D import LineLineIntersect3D, ret_WP

from macrolib.Weld import mtrl_weld

 

import os

import sys

Units("feet")

from shape import Shape

from point import Point, PointLocate

from member import Member, MemberLocate, MemberAllocated

from rect_plate import RectPlate

from weld_add import Weld

from hole_add import Hole

from job import Job

from fab import Fabricator

# startup code end

def run_script():

    try:

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

        drv_letter, drv_path = os.path.splitdrive(os.getcwd())

        ## Variables section

        # system path for defaults file

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

        # defaults file

        def_file = "Col_SafetyTabs_v1_03.txt"   # defaults file

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

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

        enable_default_import_export = "Enable"

       

        script_name = "Col_SafetyTabs_v1.03.py"

 

        # Dialog box image path and file name

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

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

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

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

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

               

        ## Defaults section

        dist_first = 22.5                   # distance from floor to cable holes

        dist_cc = 22.5                      # vertical distance center to center of cable holes

        add_lifeline_holes = "Yes"          # "Yes", "No"

        add_safety_holes = "Yes"            # "Yes", "No"

        dist_lifeline_hole = 90.0           # distance to lifeline hole above finished floor

        floor_thk = 5.5                     # floor thickness

        hole_size = 0.8125                  # hole size

       

        # column faces to add safety holes ["Face A", "Face B", "Face C", Face "D"]

        col_face_list = []                 

        tab_dim_x = 4.0                     # 'x' dimension of column

        tab_dim_y = 2.0                     # 'y' dimension of column

        tab_thk = 0.375

        tab_finish = "Yellow Zinc"

        # default steel grade Job().steel_grades("Plate").keys()

        steelgrade = "A36"

       

        ## WELDING DEFAULTS - TAIL NOTE IS NOT SUPPORTED IN THIS VERSION

        add_weld = "Yes"                    # "Yes" "No"

        # weld type is limited to 'Fillet'

        weld_type = "Fillet"                # weld type "Fillet"

        weld_size = "3/16"                  # weld size "1/8", "3/16", "1/4"

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

        ## Function definition section ##################################################

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

        # add a hole to the tab plate

        def safety_hole (rp1, hl_ref_pt, hs):

            try:

            # hole group add begin

                hole26 = Hole()

                hole26.mtrl = [rp1, ]

                hole26.pt1 = hl_ref_pt

                hole26.hole_type = "Standard Round"

                hole26.face = "NS Face"

                hole26.valid_cnc = "Yes"

                hole26.x_ref_offset = 0.0

                hole26.y_ref_offset = 0.0

                hole26.x_spa = 0.0

                hole26.y_spa = 0.0

                hole26.group_rot = 0.0

                hole26.locate = "Center"

                hole26.columns = 1

                hole26.rows = 1

                hole26.bolt_type = "Auto"

                hole26.bolt_dia = hs - 0.0625

                hole26.slot_rot = 0.0

                hole26.length = hole26.calc_slot_length()

                hole26.hole_dia = hole26.calc_hole_size()

                hole26.show_window = "Yes"

                hole26.create()

            except:

                yes_or_no("Error adding holes.\n" + formatExceptionInfo(), "OK")

            # hole group add end

 

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

        # add the tab plate

        # returns a rectangular plate object

        def tab_pl(mem, pnt1, steelgrade, dim_x, dim_y, thk, fin, rotpl, ref_pt_off):

            # rectangular plate begin

            rp1 = RectPlate()

            rp1.member = mem

            rp1.pt1 = pnt1

            rp1.pt2 = pnt1 + mem.translate(dim_x, 0.0, 0.0)

            rp1.grade = steelgrade

            rp1.origin = "Center"

            rp1.top_oper_left = "None"

            rp1.top_length_left = 0.0

            rp1.top_clip_left = 0.0

            rp1.top_oper_right = "None"

            rp1.top_length_right = 0.0

            rp1.top_clip_right = 0.0

            rp1.bottom_oper_left = "None"

            rp1.bottom_oper_right = "None"

            rp1.width = dim_y

            rp1.thick = thk

            rp1.work_pt_dist = rp1.pt1.dist( rp1.pt2 )

            rp1.setback_left = 0

            rp1.setback_right = 0

            rp1.web_cut_angle_left = 0

            rp1.web_cut_angle_right = 0

            rp1.length = rp1.pt1.dist(rp1.pt2)

            rp1.mtrl_type = "Plate"

            rp1.finish = fin

            rp1.ref_pt_offset = ref_pt_off

            rp1.add()

            rp1.rotate(rp1.member, rotpl)

            # rectangular plate end

            return rp1

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

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

        if not col_face_list:

            col_face_list = []

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

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

        while 1:

            col_list = []

            bm_list = []

            z = 1

            # Select column members

            ClearSelection()

            while z:

                try:

                    if len(col_list) == 0:

                        mem1 = MemberLocate("Select a WF, Pipe or HSS column member to receive tabs.")

                    else:

                        mem1 = MemberLocate("Select an additional WF, Pipe or HSS column member to receive tabs.")

                    if mem1 == None:

                        break

                    else:

                        if mem1.type == "Column":

                            if mem1.mtrl_type in ["W flange", "Pipe", "Tube"]:

                                col_list.append(mem1)

                            else:

                                Warning(mem1.mtrl_type + " column material is not supported.")

                        else:

                            Warning("You picked a " + mem1.type + ". You must pick a Column.")

                except:

                    yes_or_no("User canceled the operation.\n" + formatExceptionInfo(), "OK")

                    col_list = []

                    break

            if len(col_list) < 1:

                break

            z = 1

            # Select beam members

            ClearSelection()

            while z:

                try:

                    if len(bm_list) == 0:

                        mem2 = MemberLocate("Select first BEAM or JOIST member")

                    else:

                        mem2 = MemberLocate("Select additional BEAM/JOIST or RETURN")

                    if mem2 == None:

                        break

                    else:

                        if mem2.type == "Beam" or mem2.type == "Joist":

                            bm_list.append(mem2)

                        else:

                            Warning("You picked a " + mem2.type + ". You must pick a Beam or Joist.")

                except:

                    yes_or_no("User canceled the operation.\n" + formatExceptionInfo(), "OK")

                    bm_list = []

                    break

            if len(bm_list) < 1:

                Warning("You did not pick any beams. Exiting script.")

                break

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

            # begin loop for columns

            for ci in range(len(col_list)):

                

                pt_list = []

                for bi in range(len(bm_list)):

                    # Create reference point list

                    pt_list.append(ret_WP(col_list[ci], bm_list[bi])[0])

                   

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

                dlg1 = Dialog( "Add safety tab plates to column #" + str(ci+1))

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

                dlg1.tabset_begin()

                dlg1.tab("General Information")

                dlg1.column_group_begin()

                dlg1.column(0)

                dlg1.group_title("General Information")

                dlg1.menu("add_safety_holes", ("Yes", "No"), add_safety_holes, "Add safety cable tab plates")

                dlg1.menu("add_lifeline_holes", ("Yes", "No"), add_lifeline_holes, "Add lifeline tab plates")

                dlg1.group_title_end

 

                # checkbutton automatically is formatted as a group title       

                dlg1.checkbutton("col_face_list", ["Face A", "Face B", "Face C", "Face D"], col_face_list, "Column Face Selection")

 

                dlg1.group_title("Column Information")

                dlg1.line("Selected Column Size: %s        Piecemark: %s" % (col_list[ci].size, col_list[ci].piecemark))

                dlg1.line("Plan Rotation: " + "%0.4f      Location: %s, %s, %s" % (col_list[ci].plan_rotation,\

                                                                                   dim_print(col_list[ci].left_location.x),\

                                                                                   dim_print(col_list[ci].left_location.y),\

                                                                                   dim_print(col_list[ci].left_location.z)))

                dlg1.group_title_end

               

                dlg1.group_title("Safety Cable Vertical Locations")

                dlg1.entry("floor_thk", dim_print(floor_thk), "Floor thickness                         ")

                dlg1.entry("dist_first", dim_print(dist_first), "Dist from floor to 1st safety cable")

                dlg1.entry("dist_cc", dim_print(dist_cc), "C/C dist between safety cables")

                dlg1.entry("dist_lifeline_hole", dim_print(dist_lifeline_hole), "Dist from floor to lifeline")

                dlg1.group_title_end

 

                dlg1.group_title("Tab Dimensions, Grade, Finish")

                dlg1.line("Length is measured along 'X' axis of column")

                dlg1.entry("tab_thk", dim_print(tab_thk), "Tab thickness")

                dlg1.entry("tab_dim_x", dim_print(tab_dim_x), "Tab length")

                dlg1.entry("tab_dim_y", dim_print(tab_dim_y), "Tab width")

                dlg1.entry("hole_size", dim_print(hole_size), "Hole diameter")

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

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

                          tab_finish, "Select tab finish" )

                dlg1.group_title_end

               

                dlg1.column(0)

                dlg1.image(image_name)

                dlg1.column_group_end()

               

                dlg1.tab("Weld")

                dlg1.group_title("Information")

                dlg1.menu("add_weld", ("Yes", "No"), add_weld, "Add weld?")

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

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

                dlg1.group_title_end

                dlg1.group_title("Weld Images")

                dlg1.column_group_begin()

                dlg1.column(0)

                dlg1.image(image_name1)

                dlg1.column(0)

                dlg1.image(image_name2)

                dlg1.column_group_end()

                dlg1.group_title_end

                dlg1.tab("DE Image")

                dlg1.group_title("Untouched Drawing Editor Image")

                dlg1.image(image_name3)

                dlg1.group_title_end

                dlg1.tabset_end()

               

                try:

                    dd1 = dlg1.done()

                except ResponseNotOK:

                    break

                # Update the local namespace

                for key, value in dd1.items():

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

                    

                if col_face_list == None:

                    dd1['col_face_list'] = []

                    col_face_list = []

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

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

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

                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)

                   

                # Determine column depth and width dimensions

                if col_list[ci].mtrl_type == "W flange":

                    column_depth = col_list[ci].depth

                    column_width = col_list[ci].tw

                elif col_list[ci].mtrl_type == "Pipe":

                    column_depth = col_list[ci].depth

                    column_width = col_list[ci].depth

                else:

                    column_depth = col_list[ci].long_depth

                    column_width = col_list[ci].short_depth

                    

                # Begin loop for beams, add tab plates with holes

                for bi in range(len(bm_list)):

                   

                    if "Face A" in col_face_list:

                        # set material reference point offset to hole location

                        ref_pt_off = (tab_dim_x/2.0, -tab_dim_y/2.0, 0.000000)

                        if add_safety_holes == "Yes":

                            hole_WP1 = pt_list[bi] + col_list[ci].translate(dist_first + floor_thk, column_depth/2 + tab_dim_y/2, 0.0)

                            hole_WP2 = pt_list[bi] + col_list[ci].translate(dist_first + floor_thk + dist_cc, column_depth/2 + tab_dim_y/2, 0.0)

                            rp1 = tab_pl(col_list[ci], pt_list[bi] + col_list[ci].translate(dist_first + floor_thk - tab_dim_x/2, column_depth/2, 0.0), \

                                         steelgrade, tab_dim_x, tab_dim_y, tab_thk, tab_finish, (180.0, 0.0, 0.0), ref_pt_off)

                            safety_hole (rp1, hole_WP1, hole_size)

                            rp2 = tab_pl(col_list[ci], pt_list[bi] + col_list[ci].translate(dist_first + floor_thk + dist_cc - tab_dim_x/2, column_depth/2, 0.0), \

                                         steelgrade, tab_dim_x, tab_dim_y, tab_thk, tab_finish, (180.0, 0.0, 0.0), ref_pt_off)

                            safety_hole (rp2, hole_WP2, hole_size)

                            if add_weld == "Yes":

                                mtrl_weld([col_list[ci], ], [rp1, ], weld_size, weld_type)

                                mtrl_weld([col_list[ci], ], [rp2, ], weld_size, weld_type)

                               

                        if add_lifeline_holes == "Yes":

                            hole_WP3 = pt_list[bi] + col_list[ci].translate(dist_lifeline_hole + floor_thk, column_depth/2 + tab_dim_y/2, 0.0)

                            rp1 = tab_pl(col_list[ci], pt_list[bi] + col_list[ci].translate(dist_lifeline_hole + floor_thk - tab_dim_x/2, column_depth/2, 0.0), \

                                         steelgrade, tab_dim_x, tab_dim_y, tab_thk, tab_finish, (180.0, 0.0, 0.0), ref_pt_off)

                            safety_hole (rp1, hole_WP3, hole_size)

                            if add_weld == "Yes":

                                mtrl_weld([col_list[ci], ], [rp1, ], weld_size, weld_type)

 

                    if "Face B" in col_face_list:

                        # set material reference point offset to hole location

                        ref_pt_off = (tab_dim_x/2.0, -tab_dim_y/2.0, 0.000000)

                        if add_safety_holes == "Yes":

                            hole_WP1 = pt_list[bi] + col_list[ci].translate(dist_first + floor_thk, 0.0, column_width/2 + tab_dim_y/2)

                            hole_WP2 = pt_list[bi] + col_list[ci].translate(dist_first + floor_thk + dist_cc, 0.0, column_width/2 + tab_dim_y/2)

                            rp1 = tab_pl(col_list[ci], pt_list[bi] + col_list[ci].translate(dist_first + floor_thk - tab_dim_x/2, 0.0, column_width/2), \

                                         steelgrade, tab_dim_x, tab_dim_y, tab_thk, tab_finish, (-90.0, 0.0, 0.0), ref_pt_off)

                            safety_hole (rp1, hole_WP1, hole_size)

                            rp2 = tab_pl(col_list[ci], pt_list[bi] + col_list[ci].translate(dist_first + floor_thk + dist_cc - tab_dim_x/2, 0.0, column_width/2), \

                                         steelgrade, tab_dim_x, tab_dim_y, tab_thk, tab_finish, (-90.0, 0.0, 0.0), ref_pt_off)

                            safety_hole (rp2, hole_WP2, hole_size)

                            if add_weld == "Yes":

                                mtrl_weld([col_list[ci], ], [rp1, ], weld_size, weld_type)

                                mtrl_weld([col_list[ci], ], [rp2, ], weld_size, weld_type)

                               

                        if add_lifeline_holes == "Yes":

                            hole_WP3 = pt_list[bi] + col_list[ci].translate(dist_lifeline_hole + floor_thk, 0.0, column_width/2 + tab_dim_y/2)

                            rp1 = tab_pl(col_list[ci], pt_list[bi] + col_list[ci].translate(dist_lifeline_hole + floor_thk - tab_dim_x/2, 0.0, column_width/2), \

                                         steelgrade, tab_dim_x, tab_dim_y, tab_thk, tab_finish, (-90.0, 0.0, 0.0), ref_pt_off)

                            safety_hole (rp1, hole_WP3, hole_size)

                            if add_weld == "Yes":

                                mtrl_weld([col_list[ci], ], [rp1, ], weld_size, weld_type)

                           

                    if "Face D" in col_face_list:

                        # set material reference point offset to hole location

                        ref_pt_off = (tab_dim_x/2.0, -tab_dim_y/2.0, 0.000000)

                        if add_safety_holes == "Yes":

                            hole_WP1 = pt_list[bi] + col_list[ci].translate(dist_first + floor_thk, 0.0, -column_width/2 - tab_dim_y/2)

                            hole_WP2 = pt_list[bi] + col_list[ci].translate(dist_first + floor_thk + dist_cc, 0.0, -column_width/2 - tab_dim_y/2)

                            rp1 = tab_pl(col_list[ci], pt_list[bi] + col_list[ci].translate(dist_first + floor_thk - tab_dim_x/2, 0.0, -column_width/2), \

                                         steelgrade, tab_dim_x, tab_dim_y, tab_thk, tab_finish, (90.0, 0.0, 0.0), ref_pt_off)

                            safety_hole (rp1, hole_WP1, hole_size)

                            rp2 = tab_pl(col_list[ci], pt_list[bi] + col_list[ci].translate(dist_first + floor_thk + dist_cc - tab_dim_x/2, 0.0, -column_width/2), \

                                         steelgrade, tab_dim_x, tab_dim_y, tab_thk, tab_finish, (90.0, 0.0, 0.0), ref_pt_off)

                            safety_hole (rp2, hole_WP2, hole_size)

                            if add_weld == "Yes":

                                mtrl_weld([col_list[ci], ], [rp1, ], weld_size, weld_type)

                                mtrl_weld([col_list[ci], ], [rp2, ], weld_size, weld_type)

                               

                        if add_lifeline_holes == "Yes":

                            hole_WP3 = pt_list[bi] + col_list[ci].translate(dist_lifeline_hole + floor_thk, 0.0, -column_width/2 - tab_dim_y/2)

                            rp1 = tab_pl(col_list[ci], pt_list[bi] + col_list[ci].translate(dist_lifeline_hole + floor_thk - tab_dim_x/2, 0.0, -column_width/2), \

                                         steelgrade, tab_dim_x, tab_dim_y, tab_thk, tab_finish, (90.0, 0.0, 0.0), ref_pt_off)

                            safety_hole (rp1, hole_WP3, hole_size)

                            if add_weld == "Yes":

                                mtrl_weld([col_list[ci], ], [rp1, ], weld_size, weld_type)

                   

                    if "Face C" in col_face_list:

                        # set material reference point offset to hole location

                        ref_pt_off = (tab_dim_x/2.0, -tab_dim_y/2.0, 0.000000)

                        if add_safety_holes == "Yes":

                            hole_WP1 = pt_list[bi] + col_list[ci].translate(dist_first + floor_thk, -column_depth/2 - tab_dim_y/2, 0.0)

                            hole_WP2 = pt_list[bi] + col_list[ci].translate(dist_first + floor_thk + dist_cc, -column_depth/2 - tab_dim_y/2, 0.0)

                            rp1 = tab_pl(col_list[ci], pt_list[bi] + col_list[ci].translate(dist_first + floor_thk - tab_dim_x/2, -column_depth/2, 0.0), \

                                         steelgrade, tab_dim_x, tab_dim_y, tab_thk, tab_finish, (0.0, 0.0, 0.0), ref_pt_off)

                            safety_hole (rp1, hole_WP1, hole_size)

                            rp2 = tab_pl(col_list[ci], pt_list[bi] + col_list[ci].translate(dist_first + floor_thk + dist_cc - tab_dim_x/2, -column_depth/2, 0.0), \

                                         steelgrade, tab_dim_x, tab_dim_y, tab_thk, tab_finish, (0.0, 0.0, 0.0), ref_pt_off)

                            safety_hole (rp2, hole_WP2, hole_size)

                            if add_weld == "Yes":

                                mtrl_weld([col_list[ci], ], [rp1, ], weld_size, weld_type)

                                mtrl_weld([col_list[ci], ], [rp2, ], weld_size, weld_type)

                               

                        if add_lifeline_holes == "Yes":

                            hole_WP3 = pt_list[bi] + col_list[ci].translate(dist_lifeline_hole + floor_thk, -column_depth/2 - tab_dim_y/2, 0.0)

                            rp1 = tab_pl(col_list[ci], pt_list[bi] + col_list[ci].translate(dist_lifeline_hole + floor_thk - tab_dim_x/2, -column_depth/2, 0.0), \

                                         steelgrade, tab_dim_x, tab_dim_y, tab_thk, tab_finish, (0.0, 0.0, 0.0), ref_pt_off)

                            safety_hole (rp1, hole_WP3, hole_size)

                            if add_weld == "Yes":

                                mtrl_weld([col_list[ci], ], [rp1, ], weld_size, weld_type)

            if print_doc == "No":

                Add_safety = yes_or_no("Add safety tab plates to more WF, Pipe or HSS columns")

                if Add_safety == 0:

                    break

            else: break

    except:

        Warning(formatExceptionInfo())

## END run_script() ###########################################################

if __name__ == '__main__':

    try:

        run_script()

    finally:

        ClearSelection()

        del run_script