##  Embed_Angle.py Version 1.07

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

##  All rights reserved.

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

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

""" Embed_Angle.py

    Add an embedded angle miscellaneous member with studs.

    User picks end points of the member.

    User must be in plan and the embed should be flat to produce the intended results.

    Studs will be applied to the inside of the angle at 45 degrees (Corner 45).

    Studs applied to both angle legs will be staggered.

    Nailer holes can be added in the vertical leg.

   

    The user must manually modify the member description.

    The user must modify the member views in member isolation.

    You cannot assign a sequence through parametrics (yet).

 

    NOTE:

    This script will read and write the defaults to a disk file if so enabled in the

    "Defaults section". The first time the script is executed the defaults file will

    be created. Subsequent script executions will import the defaults used in the

    previous execution. Set the variable "enable_default_import_export" to "Disable"

    to disable this feature.

   

    Originally developed in SDS2 7.021 1/31/06 (R1)

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

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

 

    Version 1.02 (2/3/06) -     Add path for defaults file. Go to "Variables" to modify system path.

    Version 1.03 (2/17/06) -    Revise the way stud material is added.

    Version 1.04 (3/15/07) -    Add code to adjust angle rotations for SDS/2 Versions 7.023 and higher.

                                Drop support for sloping angles.

                                This version will not work in SDS/2 versions prior to 7.023.

                                Read/save default files - subdirectory 'SDS/2 root data'/macro/Defaults

                                Image files - subdirectory 'SDS/2 root data'/macro/Images

    Version 1.05 (3/16/07) -    Corrected image path

    Version 1.06 (3/17/07) -    Update code

                                Import modules

                                Options to apply the studs to the angle legs

    Version 1.07 (4/2/07) -     Initialize defaults as floats where appropriate.

 

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

    ****NOTE: This version is not compatible with SDS/2 versions prior to 7.023 ****

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

   

    Go to "Defaults section" to modify script defaults.

"""

def run_script():

    # startup code begin

    import os

    from math import cos, pi, tan, atan2, atan, sin

    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.angle import rtod, dtor, calc_plan_rotation

    from macrolib.stud_info import stud_dim

    from macrolib.PolarPt import polar_pt_hor

 

    Units("feet")

    from shape import Shape

    from point import Point, PointLocate

    from member import Member, MemberLocate

    from mtrl_list import MtrlLocate, HoleLocate

    from rolled_section import RolledSection

    from hole_add import Hole

    from shr_stud import ShrStud

    from job import Job

    from fab import Fabricator

 

    # startup code end

 

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

    # system path for defaults file

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

    # defaults file

    def_file = "Embed_Angle.txt"

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

    enable_default_import_export = "Enable"

    script_name = "Embed_Angle_v1.07.py"

 

    # Dialog box image path and file name

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

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

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

 

    # a stud will not be placed closer than this distance to the end of the member

    min_dist = 2.5

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

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

    Job_object = Job()

    embed_size = "L4x3x1/4"

    # "User" "System" Create user piece mark or system piece mark

    embed_mark_system_user = "User"

    user_piece_mark = "XXXX"

 

    # stud diameter ("1/4", "3/8", "1/2", "5/8", "3/4", "7/8", "1")  

    stud_diam = "1/2"                                   

    stud_length = 4.125

    stud_color = "Yellow Zinc"

    # stud spacing along miscellaneous member x-axis

    x_spa = 24.0

    # ("None", "Ends", "Spacing")

    add_nailer_holes = "Spacing"

    nailer_hole_spacing = 24.0

    # nailer hole edge distance

    nailer_edge_dist = 1.0

    # nailer hole size

    nailer_hole_size = 0.5625

    # nailer hole gage

    nailer_gage = 2.0

    # offset "Spacing" hole pattern to miss studs where user deems necessary

    nailer_offset = 1.5

    # material grade Job_object.steel_grades("Angle").keys()

    angle_grade = Job_object.steel_grades("Angle").keys()[0]

    # ("HZ.", "VT.")

    angle_orient = "VT."

    # ("In", "Out") "Out" will toe angle toward top of screen (left to right selected points)

    angle_toe_in_or_out = "Out"

   

    # Stud placement

    # ("Corner 45", "Vert Leg", "Hor Leg", "Both Legs")

    stud_placement = "Corner 45"

    vert_dim = 4.0

    hor_dim = 2.5

    # If both legs is selected, studs will be staggered.

    ## End defaults section

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

    ## Function definitions

    def apply_stud(mem, pt11, pt12, _stud_diam, _head_thk, _head_diam, _stud_color):

        # shear stud begin

        m1 = ShrStud()

        m1.member = mem

        m1.pt1 = pt11

        m1.pt2 = pt12

        m1.stud_dia = _stud_diam

        m1.head_thick = _head_thk

        m1.head_dia = _head_diam

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

        m1.mtrl_type = "Shear stud"

        m1.finish = _stud_color

        m1.ref_pt_offset = (0.000000, 0.000000, 0.000000)

        m1.add()

        # m1.rotate(m1.member, rot_args)

        # shear stud end

 

    # define function to add the miscellaneous member, rolled material

    def add_misc_rolled_section(pnt1, pnt2, mtrl_size, grade, mk, orient, ld, rot): # orient = "HZ." or "VT."

        # member begin

        memadd1 = Member('Misc Rolled Section')

        memadd1.left.location = pnt1

        memadd1.right.location = pnt2

        memadd1.section_size = mtrl_size

        memadd1.grade = grade

        memadd1.piecemark = mk

        memadd1.centered = "No"

        memadd1.llv = orient

        memadd1.toeio = ld

        memadd1.rolling_op = "None"

        memadd1.work_pt_dist = memadd1.left.location.dist(memadd1.right.location)

        memadd1.setback_left = 0

        memadd1.setback_right = 0

        memadd1.end_cut_left = "Standard Cut"

        memadd1.end_cut_right = "Standard Cut"

        memadd1.length = memadd1.work_pt_dist - memadd1.setback_left - memadd1.setback_right

        memadd1.mtrl_type = "Angle"

        memadd1.mtrl_usage = "EMBED"

        memadd1.finish = "Gray oxide"

        memadd1.ref_pt_offset = (0, 0, 0)

        memadd1.add()

        memadd1.rotate(rot)

        # member end

        return memadd1

    # function to add holes to the embedded plate

 

    def ang_holes (mem, ref_pt, face, dist_1st, ga, pattern_orientation, hz, cols, spa):

        try:

            # hole group add begin

            hole26 = Hole()

            hole26.mtrl = [mem, ]

            hole26.pt1 = ref_pt

            hole26.hole_type = "Standard Round"

            hole26.face = face

            hole26.valid_cnc = "Yes"

            hole26.x_ref_offset = dist_1st

            hole26.y_ref_offset = ga

            hole26.x_spa = spa

            hole26.y_spa = 3.0

            hole26.group_rot = 0.0

            hole26.locate = pattern_orientation

            hole26.columns = cols

            hole26.rows = 1

            hole26.bolt_type = "Auto"

            hole26.bolt_dia = hz - 0.0625

            hole26.hole_dia = hz

            hole26.show_window = "No"

            hole26.create()

        except:

            pass

        # hole group add end

        return hole26

 

    # end function definitions

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

    ## Import default values 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:

        ptWP1 = PointLocate("Pick angle embed start point")

        if ptWP1 == None:

            break

        ptWP2 = PointLocate("Pick angle embed end point")

        # determine stud dimensions based upon stud diameter

        head_thk, head_diam, burn_off = stud_dim(dim(stud_diam))

 

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

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

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

        dlg1 = Dialog( "Create an embedded angle member" )

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

       

        dlg1.tabset_begin()

        dlg1.tab("Embed general information")

        dlg1.line("Input length of embedded angle = " + dim_print(ptWP1.dist(ptWP2)))

       

        dlg1.group_title("Embedded angle size, piece mark and material grade")

        dlg1.entry("embed_size", embed_size, "Embed angle size                                                     ")

        dlg1.menu("embed_mark_system_user", ("User", "System"), embed_mark_system_user, "User or System Piece Mark")

        dlg1.entry("user_piece_mark", user_piece_mark, "User Piece Mark")

        dlg1.menu("angle_grade", Job_object.steel_grades("Angle").keys(), angle_grade, "Angle Material Grade")

        dlg1.group_title_end

       

        dlg1.group_title("Embed angle orientation")

        dlg1.menu("angle_orient", ("VT.", "HZ."), angle_orient, "Long leg vertical or horizontal (where applicable)")

        dlg1.menu("angle_toe_in_or_out", ("In", "Out"), angle_toe_in_or_out, "Horizontal leg IN or Out")

        dlg1.group_title_end

       

        dlg1.tab("Stud Information")

        dlg1.line("Input length of embedded angle = " + dim_print(ptWP1.dist(ptWP2)))

        dlg1.group_title("Stud placement")

        dlg1.menu("stud_placement", ("Corner 45", "Vert Leg", "Hor Leg", "Both Legs"), stud_placement, "Stud placement")

        dlg1.entry("vert_dim", dim_print(vert_dim), "Gage on vert leg")

        dlg1.entry("hor_dim", dim_print(hor_dim), "Gage on hor leg")

        # dlg1.menu("stagger", ('Yes', 'No'), stagger, "Stagger studs ('Both Legs' option)")

        dlg1.group_title_end

       

        dlg1.group_title("Stud attributes")

        dlg1.label(dim_print(head_diam) + " diam. x " + dim_print(head_thk), "Stud head dimensions for default stud diameter: ")

        dlg1.label(dim_print(burn_off), "Burn off for default diameter: ")

        dlg1.menu("stud_diam", ("1/4", "3/8", "1/2", "5/8", "3/4", "7/8", "1"), stud_diam, "Stud diameter")

        dlg1.entry("stud_length", dim_print(stud_length), "Stud length")

        dlg1.menu("stud_color", finishList, stud_color, "Color of stud material")

        dlg1.group_title_end

       

        dlg1.group_title("Stud Pattern")

        dlg1.line("Member Line Plan Length = " + dim_print(ptWP1.dist(ptWP2)))

        dlg1.entry("x_spa", dim_print(x_spa), "Horizontal stud spacing")

        dlg1.group_title_end

       

        dlg1.tab("Nailer Holes")

        dlg1.line("Input length of embedded angle = " + dim_print(ptWP1.dist(ptWP2)))

        dlg1.group_title("Nailer holes basic options")

        dlg1.menu("add_nailer_holes", ("None", "Ends", "Spacing"), add_nailer_holes, "Nailer holes option          ")

        dlg1.entry("nailer_hole_size", dim_print(nailer_hole_size), "Nailer hole size")

        dlg1.entry("nailer_gage", dim_print(nailer_gage), "Nailer hole gage in vertical leg")

        dlg1.group_title_end

       

        dlg1.group_title("Nailer holes 'Spacing' option")

        dlg1.entry("nailer_hole_spacing", dim_print(nailer_hole_spacing), "Nailer hole spacing")

        dlg1.entry("nailer_offset", dim_print(nailer_offset), "Nailer hole pattern offset to miss studs where necessary")

        dlg1.group_title_end

       

        dlg1.group_title("Nailer holes 'Ends' option")

        dlg1.entry("nailer_edge_dist", dim_print(nailer_edge_dist), "Nailer hole edge distance")

        dlg1.group_title_end

       

        dlg1.tab("Graphic Images")

        dlg1.column_group_begin()

        dlg1.column(2)

        dlg1.image(image_name1)

        dlg1.column(2)

        dlg1.image(image_name2)

        dlg1.column_group_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

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

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

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

           

        try:

            mat_thk = Shape(embed_size).thick

        except:

            Warning ("The material size you entered is not in the material file")

            break

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

       

        if embed_mark_system_user == "System":

            _mark_ = ""

        else:

            _mark_ = user_piece_mark

 

        # Add member

        if Shape(embed_size).LL_depth == Shape(embed_size).SL_depth:

            angle_orient == "VT."

           

        # Versions 1.04 and higher do not support sloping members

        vert_rotate, horiz_rotate = calc_plan_rotation(ptWP1, ptWP2)

       

        if angle_toe_in_or_out == "In":

            if horiz_rotate > 90.0 or horiz_rotate <= -90.0:

                rot_mem = (0.0, 0.0, 180.0)

            else:

                rot_mem = (0.0, 0.0, 0.0)

            leg_dir = "Out"

        else:

            if horiz_rotate > 90.0 or horiz_rotate <= -90.0:

                rot_mem = (180.0, 0.0, 180.0)

            else:

                rot_mem = (180.0, 0.0, 0.0)

            leg_dir = "In"

           

        mem_added = add_misc_rolled_section(ptWP1, ptWP2, embed_size, angle_grade, _mark_, angle_orient, leg_dir, rot_mem)

       

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

        # Add studs

        head_thk, head_diam, burn_off = stud_dim(dim(stud_diam))

        no_spa = int(((ptWP1.dist(ptWP2)) - (2 * min_dist)) / x_spa)

        dist_left = ((ptWP1.dist(ptWP2)) - (no_spa*x_spa)) / 2

        # Material rotation is not required if material is added between two calculated points

        if angle_toe_in_or_out == "Out":

            # studs above material axis

            # rot_mat = (0.0, 225.000000, horiz_rotate - 90.0) # stud rotation

            y_off = -mat_thk - (dim(stud_diam) * 0.35355)

            z_off = -y_off

            point2_zoff = stud_length / 2**0.5

            y_dir = 1

            z_dir = 1

        else:

            # studs below material axis

            # rot_mat = (0.0, -45.000000, horiz_rotate - 90.0) # stud rotation

            y_off = -mat_thk - (dim(stud_diam) * 0.35355)

            z_off = y_off

            point2_zoff = -stud_length / 2**0.5

            y_dir = -1

            z_dir = -1

           

        x_dist = 0.0

 

        # ("Corner 45", "Vert Leg", "Hor Leg", "Both Legs")

        if stud_placement == "Corner 45":

            point1 = mem_added.main_mtrl().pt1 + mem_added.main_mtrl().translate (dist_left, y_off, z_off)

            for i in range(no_spa + 1):

                x_dist = i*x_spa

                ptWP = point1 + mem_added.main_mtrl().translate(x_dist, 0.0, 0.0)

                ptWP0 = ptWP + mem_added.main_mtrl().translate(0.0, -stud_length / 2**0.5, point2_zoff)

                apply_stud(mem_added, ptWP, ptWP0, dim(stud_diam), head_thk, head_diam, stud_color)

           

        if stud_placement in ["Vert Leg", "Both Legs"]:

            y_off = -mat_thk

            z_off = vert_dim*z_dir

            point1 = mem_added.main_mtrl().pt1 + mem_added.main_mtrl().translate (dist_left, y_off, z_off)

            for i in range(no_spa + 1):

                x_dist = i*x_spa

                ptWP = point1 + mem_added.main_mtrl().translate(x_dist, 0.0, 0.0)

                ptWP0 = ptWP + mem_added.main_mtrl().translate(0.0, -stud_length, 0.0)

                if stud_placement == "Vert Leg" or i%2 == 0:

                    apply_stud(mem_added, ptWP, ptWP0, dim(stud_diam), head_thk, head_diam, stud_color)

 

        if stud_placement in ["Hor Leg", "Both Legs"]:

            y_off = -hor_dim

            z_off = mat_thk*z_dir

            point1 = mem_added.main_mtrl().pt1 + mem_added.main_mtrl().translate (dist_left, y_off, z_off)

            for i in range(no_spa + 1):

                x_dist = i*x_spa

                ptWP = point1 + mem_added.main_mtrl().translate(x_dist, 0.0, 0.0)

                ptWP0 = ptWP + mem_added.main_mtrl().translate(0.0, 0.0, z_dir*stud_length)

                if stud_placement == "Hor Leg" or i%2 == 1:

                    apply_stud(mem_added, ptWP, ptWP0, dim(stud_diam), head_thk, head_diam, stud_color)

 

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

           

        # Add nailer holes

        if angle_orient == "VT.":

            hl_face = 4

            maximum_gage = Shape(embed_size).LL_depth - 0.75

        else:

            hl_face = 1

            maximum_gage = Shape(embed_size).SL_depth - 0.75

           

        if nailer_gage > maximum_gage:

            nailer_gage = maximum_gage

           

        if leg_dir == "In":

            patt = "Below Right"

        else:

            patt = "Above Right"

           

        if add_nailer_holes == "Ends":

            dist_hl_to_hole = ptWP1.dist(ptWP2)- (nailer_edge_dist * 2)

            ang_holes (mem_added, mem_added.main_mtrl().pt1, hl_face, nailer_edge_dist, nailer_gage, patt, nailer_hole_size, 2, dist_hl_to_hole)

           

        if add_nailer_holes == "Spacing":

            no_spa = int(((ptWP1.dist(ptWP2)) - (2 * nailer_edge_dist)) / nailer_hole_spacing)

            dist_left = nailer_offset + (((ptWP1.dist(ptWP2)) - (no_spa*nailer_hole_spacing)) / 2)

            ang_holes (mem_added, mem_added.main_mtrl().pt1, hl_face, dist_left, nailer_gage, patt, nailer_hole_size, (no_spa + 1), nailer_hole_spacing)

       

## End run_script()

if __name__ == '__main__':

    try:

        run_script()

    finally:

        del run_script