##  Beam_Flg_Prep_Field_v1.04.py

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

##  All rights reserved.

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

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

"""

    Beam Flange Preparations for Field Welds (welds are accessed from above flange)

    See Steelfab drafting standard DS-21

 

    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)

 

    Version History:

    1.01 (12/18/06) - Modified code

    1.03 (02/14/07) - Rework point calculations

    1.04 (08/01/07) - Modify to work in SDS/2 7.1xx

 

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

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

 

"""

import sys, os

from math import tan, atan2, asin

 

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

from member import Member, MemberLocate, MemberAllocated

from point import Point

from mtrl_cut import MtrlCut

 

def run_script():

    # startup code begin

    from macrolib.FileDefaults import import_data, export_data

    from macrolib.MemCnt import member_count

    from macrolib.angle import rtod, dtor

    from macrolib.ExceptWarn import formatExceptionInfo

 

    Units("feet")

    # startup code end

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

    ## Variables section

    # system path for defaults file

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

    # defaults file

    def_file = "Beam_Flg_Prep_Field.txt"

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

    enable_default_import_export = "Enable"

 

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

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

 

    ## Defaults section

    # prep angle in degrees

    prep_angle = 45.0

    # ["Top Left", "Bottom Left", "Top Right", "Bottom Right", "None"]

    prep_list = ["Top Left", "Bottom Left"]                

    flush_upper_left = 0.5

    flush_lower_left = 0.5

    flush_upper_right = 0.5

    flush_lower_right = 0.5

    flange_setback_top = 0.25

    flange_setback_bott = 0.25

    access_hole_length = 1.25

    access_hole_height = 1.25

    access_hole_radius = 0.5

    ## End Variables and Defaults sections

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

    # Function definitions

    # Define function to make cut with flush flange

    def flange_prep_flush(mem, p1, p2, p3, p4, p5, p6, p7, p8, r):

        # mtrl cut begin

        mcut1 = MtrlCut()

        mcut1.mtrl = [mem, ]

        mcut1.rotate = (0,0,0)

        mcut1.pts.append( (p1, 0) )

        mcut1.pts.append( (p2, 0) )

        mcut1.pts.append( (p3, 0) )

        mcut1.pts.append( (p4, 0) )

        mcut1.pts.append( (p5, r) )

        mcut1.pts.append( (p6, r) )

        mcut1.pts.append( (p7, 0) )

        mcut1.pts.append( (p8, 0) )

        mcut1.pts.append( (p1, 0) )

        mcut1.cut("Layout")

        # mtrl cut end

 

    def hole_xy(h, len, r):

        s = ((len-r)**2 + (h-r)**2)**0.5

        # return rise on base of access_hole_length

        return len * (tan(atan2(h-r, len-r) - asin(r/s)))

       

    # End function definitions

   

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

    ## import defaults data if enabled

    if enable_default_import_export == "Enable":

        dd0 = import_data(os.path.join(default_file_path, def_file))

        if dd0:

            for key, value in dd0.items():

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

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

    

    ## Main program loop

    while 1:

        ClearSelection()

        # try:

        z = 1

        bm_list = []

       

        while z:

            mem1 = MemberLocate("Select WF BEAM Member")

            if mem1 == None:

                break

            else:

                if mem1.type in ["Beam", ]:

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

                        z = 0           # Limit selection to one member

                        bm_list.append(mem1)

                    else:

                        Warning("%s material is not supported." % (mem1.mtrl_type))

                else:

                    Warning("You picked a %s. You must pick a Beam." % (mem1.type))

 

        if len(bm_list) < 1:

            break

       

        chk_mem_list = member_count(bm_list[0])

       

        if len(chk_mem_list) > 1:

            if yes_or_no("Add flange preparations to all members with the same piecemark \r(%s members with mark %s)" % (len(chk_mem_list), mem1.piecemark)) == 1:

                bm_list = chk_mem_list

 

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

        ##  Dialog Box 1

        dlg1 = Dialog( "Prepare WF Beam Flanges for CP Welds" )

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

        dlg1.tabset_begin()

        dlg1.tab("Prep general information")

        dlg1.entry("prep_angle", prep_angle, "Angle of weld preparation                             ")

        dlg1.entry("flange_setback_top", dim_print(flange_setback_top), "End of TOP flange setback")

        dlg1.entry("flange_setback_bott", dim_print(flange_setback_bott), "End of BOTT flange setback")

        dlg1.checkbutton("prep_list", ["Top Left", "Bottom Left", "Top Right", "Bottom Right", "None"], prep_list, "Select location(s) of preparations")

        dlg1.tab("Access hole dimensions")

        dlg1.line("Access hole length is the sum of distances flange setback, corner of prep, cut flush, and hole length")

        dlg1.group_title("Dimensions")

        dlg1.entry("access_hole_height", dim_print(access_hole_height), "Access hole height")

        dlg1.entry("access_hole_length", dim_print(access_hole_length), "Access hole length")

        dlg1.entry("access_hole_radius", dim_print(access_hole_radius), "Access hole radius")

        dlg1.group_title_end

        dlg1.group_title("Cut flush dimensions")

        dlg1.entry("flush_upper_left", dim_print(flush_upper_left), "Cut flush distance TOP LEFT")

        dlg1.entry("flush_lower_left", dim_print(flush_lower_left), "Cut flush distance BOTTOM LEFT")

        dlg1.entry("flush_upper_right", dim_print(flush_upper_right), "Cut flush distance TOP RIGHT")

        dlg1.entry("flush_lower_right", dim_print(flush_lower_right), "Cut flush distance BOTTOM RIGHT")

        dlg1.group_title_end

        dlg1.tab("Graphic Image")

        dlg1.image(image_name2)

        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

        '''

        for key in dd1:

            print key, eval(key), type(eval(key))

        '''

        if prep_list == None or "None" in prep_list:

            prep_list = ["None", ]

            dd1['prep_list'] = ["None", ]

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

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

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

        if print_doc == "Yes":

            print __doc__

           

        # check for invalid radius

        if access_hole_radius > (access_hole_height / 2):

            access_hole_radius = (access_hole_height / 2)

 

        dd1['access_hole_radius'] = access_hole_radius           

 

        # Export defaults to disk if enabled

        if enable_default_import_export == "Enable":

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

        """       

        except:

            yes_or_no("User Canceled.\n\n" + formatExceptionInfo(), "OK")

            break

        """

        y_off = hole_xy(access_hole_height, access_hole_length, access_hole_radius)

        for bm in bm_list:

            if "Top Left" in prep_list:

                ptWP1 = bm.left.location + bm.translate\

                        (bm.left.setback + flange_setback_top + (bm.tf+0.999)*tan(dtor(prep_angle)) +\

                         ((bm.tf-0.001)*tan(dtor(bm.left.web_cut_angle))), 1.0, 0.0)

                ptWP2 = bm.left.location + bm.translate\

                        (bm.left.setback + flange_setback_top + (bm.tf-0.001)*tan(dtor(prep_angle)) +\

                         ((bm.tf-0.001)*tan(dtor(bm.left.web_cut_angle))), 0.0, 0.0)

                ptWP3 = ptWP2 + bm.translate(-((bm.tf+0.001)*tan(dtor(prep_angle))), -(bm.tf+0.001), 0.0)

                ptWP4 = ptWP3 + bm.translate(flush_upper_left, 0.0, 0.0)

                ptWP5 = ptWP4 + bm.translate(access_hole_length, -y_off, 0.0)

                ptWP6 = ptWP5 + bm.translate(0.0, -(access_hole_height - y_off), 0.0)

                ptWP7 = bm.left.location + bm.translate(bm.left.setback - 1.0, -(bm.tf + access_hole_height + 0.001), 0.0)

                ptWP8 = ptWP7 + bm.translate(0.0, +(bm.tf + access_hole_height + 0.001) + 1.0, 0.0)

                flange_prep_flush(bm, ptWP1, ptWP2, ptWP3, ptWP4, ptWP5, ptWP6, ptWP7, ptWP8, access_hole_radius)

            if "Bottom Left" in prep_list:

                ptWP1 = bm.left.location + bm.translate\

                        (bm.left.setback - 1.0 + flange_setback_bott + ((bm.depth)*tan(dtor(bm.left.web_cut_angle))), - (bm.depth + 1.0), 0.0)

                ptWP2 = bm.left.location + bm.translate\

                        (bm.left.setback + flange_setback_bott + ((bm.depth)*tan(dtor(bm.left.web_cut_angle))), - bm.depth, 0.0)

                ptWP3 = ptWP2 + bm.translate((bm.tf+0.001)*tan(dtor(prep_angle)), (bm.tf+0.001), 0.0)

                ptWP4 = ptWP3 + bm.translate(flush_lower_left, 0.0, 0.0)

                ptWP5 = ptWP4 + bm.translate(access_hole_length, y_off, 0.0)

                ptWP6 = ptWP5 + bm.translate(0.0, access_hole_height - y_off, 0.0)

                ptWP7 = ptWP2 + bm.translate(-flange_setback_bott - (bm.tf + access_hole_height + 0.001)*tan(dtor(bm.left.web_cut_angle)),\

                                                      (bm.tf + access_hole_height + 0.001), 0.0)

                ptWP8 = ptWP7 + bm.translate(-1.0, 0.0, 0.0)

                flange_prep_flush(bm, ptWP1, ptWP2, ptWP3, ptWP4, ptWP5, ptWP6, ptWP7, ptWP8, access_hole_radius)

            if "Top Right" in prep_list:

                ptWP1 = bm.right.location + bm.translate\

                        (-(bm.right.setback + flange_setback_top + (bm.tf+0.999)*tan(dtor(prep_angle))) +\

                         ((bm.tf-0.001)*tan(dtor(bm.right.web_cut_angle))), 1.0, 0.0)

                ptWP2 = bm.right.location + bm.translate\

                        (-(bm.right.setback + flange_setback_top + (bm.tf-0.001)*tan(dtor(prep_angle))) +\

                         ((bm.tf-0.001)*tan(dtor(bm.right.web_cut_angle))), 0.0, 0.0)

                ptWP3 = ptWP2 + bm.translate(((bm.tf+0.001)*tan(dtor(prep_angle))), -(bm.tf+0.001), 0.0)

                ptWP4 = ptWP3 + bm.translate(-flush_upper_right, 0.0, 0.0)

                ptWP5 = ptWP4 + bm.translate(-access_hole_length, -y_off, 0.0)

                ptWP6 = ptWP5 + bm.translate(0.0, -(access_hole_height - y_off), 0.0)

                ptWP7 = bm.right.location + bm.translate(-(bm.right.setback - 1.0), -(bm.tf + access_hole_height + 0.001), 0.0)

                ptWP8 = ptWP7 + bm.translate(0.0, +(bm.tf + access_hole_height + 0.001) + 1.0, 0.0)

                flange_prep_flush(bm, ptWP1, ptWP2, ptWP3, ptWP4, ptWP5, ptWP6, ptWP7, ptWP8, access_hole_radius)

            if "Bottom Right" in prep_list:

                ptWP1 = bm.right.location + bm.translate\

                        (-(bm.right.setback - 1.0 + flange_setback_bott - ((bm.depth)*tan(dtor(bm.right.web_cut_angle)))), - (bm.depth + 1.0), 0.0)

                ptWP2 = bm.right.location + bm.translate\

                        (-(bm.right.setback + flange_setback_bott - ((bm.depth)*tan(dtor(bm.right.web_cut_angle)))), - bm.depth, 0.0)

                ptWP3 = ptWP2 + bm.translate(-((bm.tf+0.001)*tan(dtor(prep_angle))), (bm.tf+0.001), 0.0)

                ptWP4 = ptWP3 + bm.translate(-flush_lower_right, 0.0, 0.0)

                ptWP5 = ptWP4 + bm.translate(-access_hole_length, y_off, 0.0)

                ptWP6 = ptWP5 + bm.translate(0.0, access_hole_height - y_off, 0.0)

                ptWP7 = ptWP2 + bm.translate(flange_setback_bott - (bm.tf + access_hole_height + 0.001)*tan(dtor(bm.right.web_cut_angle)),\

                                                      bm.tf + access_hole_height + 0.001, 0.0)

                ptWP8 = ptWP7 + bm.translate(1.0, 0.0, 0.0)

                flange_prep_flush(bm, ptWP1, ptWP2, ptWP3, ptWP4, ptWP5, ptWP6, ptWP7, ptWP8, access_hole_radius)

        Add_safety = yes_or_no("Add preps to more beams?")

        if Add_safety == 0:

            ClearSelection()

            break

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

if __name__ == '__main__':

    try:

        run_script()

    finally:

        ClearSelection()

        del run_script