##  Col_Flg_Prep_Outside Version 1.02

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

##  All rights reserved.

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

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

"""

    Column Flange Preparations for Field or Shop Welds (welds are accessed from outside)

    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)

 

    Revisions:

    Version 1.02 -  Clarify locations of preparations (example "Top Left" changed to "Left End Top Flg")

 

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

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

   

"""

# startup code begin

import sys

import traceback

from param import *

from math import *

Units("feet")

saved_sds2_version = '7.023'

saved_python_version = (2, 3, 0, 'final', 0)

try:

    from shape import Shape

    from point import Point, PointLocate

    from member import Member, MemberLocate

    from mtrl_list import MtrlLocate, HoleLocate

    from cons_line import ConsLine

    from cons_circle import ConsCircle

    from rnd_plate import RndPlate

    from rect_plate import RectPlate

    from bnt_plate import BntPlate

    from rolled_section import RolledSection

    from weld_add import Weld

    from flat_bar import FlatBar

    from hole_add import Hole

    from bolt_add import Bolt

    from roll_plate import RollPl

    from sqr_bar import SqrBar

    from rnd_bar import RndBar

    from shr_stud import ShrStud

    from grate import Grate

    from grate_trd import GrateTrd

    from deck import Deck

    from mtrl_fit import MtrlFit

    from version import CurrentVersion, VersionCompare

    curr_version = CurrentVersion()

except ImportError:

    curr_version = 'None'

    def VersionCompare( v1, v2 ):

        return -1

if VersionCompare( curr_version, '6.311' ) >= 0:

    from job import Job

    from fab import Fabricator

if VersionCompare( curr_version, '6.312' ) >= 0:

    from plate_layout import PlateLayout

if VersionCompare( curr_version, '6.314' ) >= 0:

    from plate_layout import BntPlateLayout

if VersionCompare( curr_version, '6.4' ) >= 0:

    from mtrl_cut import MtrlCut

if VersionCompare( curr_version, '7.006' ) >= 0:

    from member import MemberAllocated

if VersionCompare( curr_version, '7.009' ) >= 0:

    from job import JobName

    from fab import FabricatorName

# startup code end

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

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

default_file_path = "C:/ParamDef/Flg_Prep/"             # system path for defaults file

def_file = "Col_Flg_Prep_Outside.txt"                      # defaults file name

script_name = "Col_Flg_Prep_Outside_v1.01.py"

image_name1 = "C:/ParamImg/Col_Flg_Prep1.gif"

image_name2 = "C:/ParamImg/Col_Flg_Prep2.gif"

# Defaults section

prep_angle = 45.0                                       # prep angle in degrees

prep_list = ["Right End Top Flg", "Right End Bott Flg"]                 # ["Left End Top Flg", "Left End Bott Flg", "Right End Top Flg", "Right End Bott Flg", "None"]

flush_upper_left = "1/2"

flush_lower_left = "1/2"

flush_upper_right = "1/2"

flush_lower_right = "1/2"

flange_setback = "0"

access_hole_length = "1 1/4"

access_hole_height = "1 1/4"

access_hole_radius = "1/2"

# End defaults section

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

# Function definitions

def form_script_variables():

    # All variables are defined as strings in defaults section. Defaults are saved to disk as dlg.done() defines them.

    # Default variables must be reformatted for imported data or for the second loop if not importing data.

    # Only floating point numbers need be reformatted. Integers should be formatted in the dialog box.

    global prep_angle, flush_upper_left, flush_lower_left, flush_upper_right, flush_lower_right, flange_setback

    global access_hole_length, access_hole_height, access_hole_radius

    prep_angle = dim(prep_angle)

    flush_upper_left = dim_print(dim(flush_upper_left))

    flush_lower_left = dim_print(dim(flush_lower_left))

    flush_upper_right = dim_print(dim(flush_upper_right))

    flush_lower_right = dim_print(dim(flush_lower_right))

    flange_setback = dim_print(dim(flange_setback))

    access_hole_length = dim_print(dim(access_hole_length))

    access_hole_height = dim_print(dim(access_hole_height))

    access_hole_radius = dim_print(dim(access_hole_radius))

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

## Function definitions for saving default values to disk

## See Python file "Script_Defaults.py" for usage documentation

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

def import_data(file):

    try:

        ff = open(file)

    except:

        # print "There was an error opening the default data file. Please check your directory path and that file exists."

        return 0

    else:

        dd = {}

        key_values_list = ff.readlines()[3:]

        ff.close()

        for ii in key_values_list:

            key_name, key_value = ii.split("=", 1)

            dd[key_name.strip()] = key_value.strip()

        return dd

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

def export_data(file_name, dd_list, script_name): # pass script name for default file

    try:

        f = open(file_name, "w")

        f.write("Defaults file for script " + script_name + "\nVariable Name = Value Name\n\n")

        for jj in dd_list:

            for key_name in jj.keys():

                key_value = jj[key_name]

                f.write("%s = %s\n" % (key_name, key_value))

        f.close()

    except:

        dd_list = 0

        # print "There was an error exporting the default data to disk. Please check your directory path. "

    return dd_list

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

# convert radians to degrees

def rtod ( r ):

    return (r * 180.0 / pi)

# convert degrees to radians

def dtor ( d ):

    return (d * pi / 180.0)

# 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

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

# define function to return list of members with the same piecemark

def member_count(mem):

    mem_index = 1

    no_mem = 0

    mem_list = []

    while no_mem < 100:   

        try:

            mem2 = Member(mem_index)

        except:

            mem_index = mem_index + 1

            no_mem = no_mem + 1

        else:

            if mem2.piecemark == mem.piecemark:

                mem_list.append(mem2)

            no_mem = 0

            mem_index = mem_index + 1

    return mem_list

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

# a exception handler function to format the exception info into a string for dialog display -  credit Phil Adams [padams@colloquiuminc.com]

def formatExceptionInfo(maxTBlevel=5):

      cla, exc, trbk = sys.exc_info()

      excName = cla.__name__

      try:

            excArgs = exc.__dict__["args"]

      except KeyError:

            excArgs = "<none>"

      excTb = traceback.format_tb(trbk, maxTBlevel)

      #- build the return string ready to be displayed

      _str = "Error: " + excName + "\nDesc: "

      for i in range(len(excArgs)):

            _str = _str + excArgs[i] + "\n"

      #for ii in range(len(excTb)):

      _str = _str + excTb.pop() # + "\n"

      return _str

 

#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

   

# End function definitions

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

# Main program

# Get flange prep angle from user input

while 1:

    ClearSelection()

    try:

        z = 1

        col_list = []

        while z:

            mem1 = MemberLocate("Select WF COLUMN Member")

            if mem1 == None:

                break

            else:

                if mem1.type in ["Column"]:

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

                        z = 0           # Limit selection to one member

                        col_list.append(mem1)

                    else:

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

                else:

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

        if len(col_list) < 1:

            break

        chk_mem_list = member_count(col_list[0])

        if len(chk_mem_list) > 1:

            if yes_or_no("Add flange preparations to all members with the same piecemark \r(" + str(len(chk_mem_list)) + " members with mark " + col_list[0].piecemark + ")?") == 1:

                col_list = chk_mem_list

        if enable_default_import_export == "Enable":

            try:

                globals().update(import_data(default_file_path + def_file))

                try:

                    prep_list = eval(prep_list)

                except:

                    prep_list = ["None"]

            except:

                Warning("There was a problem importing data - reverting to original defaults")

        form_script_variables()

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

        ##  Dialog Box 1

        dlg1 = Dialog( "Prepare WF Column Flanges for CP Welds From Outside" )

        dlg1.tabset_begin()

        dlg1.tab("Prep general information")

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

        dlg1.entry("flange_setback", flange_setback, "End of flange setback")

        dlg1.checkbutton("prep_list", ["BOTT End Top Flg", "BOTT End Bott Flg", "TOP End Top Flg", "TOP End Bott Flg", "None"], prep_list, "Select location(s) of preparations")

        dlg1.line("Use chamfer tool to prepare column web. See graphic image.")

        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", access_hole_height, "Access hole height")

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

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

        dlg1.group_title_end

        dlg1.group_title("Cut flush dimensions")

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

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

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

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

        dlg1.group_title_end

        dlg1.tab("Graphic Image")

        dlg1.column_group_begin()

        dlg1.column(0)

        dlg1.image(image_name1)

        dlg1.column(0)

        dlg1.image(image_name2)

        dlg1.column_group_end()

        try:

            dd1 = dlg1.done()

        except ResponseNotOK:

            break

        globals().update(dd1)       

        ## Dialog box end xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

        # check for invalid radius

        if access_hole_radius > ((access_hole_height - 0.25) / 2):

            access_hole_radius = ((access_hole_height - 0.25) / 2)   

        if enable_default_import_export == "Enable":

            export_data(default_file_path + def_file, [dd1, ], script_name)

    except:

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

        break

    if "None" in prep_list:

        prep_list = ["None", ]

    for bi in range(len(col_list)):

        if "BOTT End Top Flg" in prep_list:

            ptWP1 = col_list[bi].left.location + col_list[bi].translate\

                    (col_list[bi].left.setback + flange_setback + (col_list[bi].tf+0.999)*tan(dtor(prep_angle)) +\

                     (((col_list[bi].depth/2) - col_list[bi].tf + .001)*tan(dtor(col_list[bi].left.web_cut_angle))), ((col_list[bi].depth/2) + 1.0), 0.0)

            ptWP2 = col_list[bi].left.location + col_list[bi].translate\

                    (col_list[bi].left.setback + flange_setback + (col_list[bi].tf-0.001)*tan(dtor(prep_angle)) +\

                     (((col_list[bi].depth/2) - col_list[bi].tf + .001)*tan(dtor(col_list[bi].left.web_cut_angle))), (col_list[bi].depth/2), 0.0)

            ptWP3 = ptWP2 + col_list[bi].translate(-((col_list[bi].tf+0.001)*tan(dtor(prep_angle))), -(col_list[bi].tf+0.001), 0.0)

            ptWP4 = ptWP3 + col_list[bi].translate(flush_upper_left, 0.0, 0.0)

            ptWP5 = ptWP4 + col_list[bi].translate(access_hole_length, -0.375, 0.0)

            ptWP6 = ptWP5 + col_list[bi].translate(0.0, -(access_hole_height - 0.375), 0.0)

            ptWP7 = col_list[bi].left.location + col_list[bi].translate\

                    (col_list[bi].left.setback - 1.0 + (((col_list[bi].depth/2))*tan(dtor(col_list[bi].left.web_cut_angle))),\

                     (col_list[bi].depth/2) - (col_list[bi].tf + access_hole_height + 0.001), 0.0)

            ptWP8 = ptWP7 + col_list[bi].translate(0.0, +(col_list[bi].tf + access_hole_height + 0.001) + 1.0, 0.0)

            flange_prep_flush(col_list[bi], ptWP1, ptWP2, ptWP3, ptWP4, ptWP5, ptWP6, ptWP7, ptWP8, access_hole_radius)

        if "BOTT End Bott Flg" in prep_list:

            ptWP1 = col_list[bi].left.location + col_list[bi].translate\

                    (col_list[bi].left.setback + flange_setback + (col_list[bi].tf+0.999)*tan(dtor(prep_angle)) +\

                     (((col_list[bi].depth/2) - col_list[bi].tf + .001)*tan(dtor(col_list[bi].left.web_cut_angle))), -((col_list[bi].depth/2) + 1.0), 0.0)

            ptWP2 = col_list[bi].left.location + col_list[bi].translate\

                    (col_list[bi].left.setback + flange_setback + (col_list[bi].tf-0.001)*tan(dtor(prep_angle)) +\

                     (((col_list[bi].depth/2) - col_list[bi].tf + .001)*tan(dtor(col_list[bi].left.web_cut_angle))), -(col_list[bi].depth/2), 0.0)

            ptWP3 = ptWP2 + col_list[bi].translate(-((col_list[bi].tf+0.001)*tan(dtor(prep_angle))), (col_list[bi].tf+0.001), 0.0)

            ptWP4 = ptWP3 + col_list[bi].translate(flush_lower_left, 0.0, 0.0)

            ptWP5 = ptWP4 + col_list[bi].translate(access_hole_length, 0.375, 0.0)

            ptWP6 = ptWP5 + col_list[bi].translate(0.0, (access_hole_height - 0.375), 0.0)

            ptWP7 = col_list[bi].left.location + col_list[bi].translate\

                    (col_list[bi].left.setback - 1.0 + (((col_list[bi].depth/2))*tan(dtor(col_list[bi].left.web_cut_angle))),\

                     -(col_list[bi].depth/2) + (col_list[bi].tf + access_hole_height + 0.001), 0.0)

            ptWP8 = ptWP7 + col_list[bi].translate(0.0, -(col_list[bi].tf + access_hole_height + 0.001) - 1.0, 0.0)

            flange_prep_flush(col_list[bi], ptWP1, ptWP2, ptWP3, ptWP4, ptWP5, ptWP6, ptWP7, ptWP8, access_hole_radius)

        if "TOP End Top Flg" in prep_list:

            ptWP1 = col_list[bi].right.location + col_list[bi].translate\

                    (-(col_list[bi].right.setback + flange_setback + (col_list[bi].tf+0.999)*tan(dtor(prep_angle)) -\

                     (((col_list[bi].depth/2) - col_list[bi].tf + .001)*tan(dtor(col_list[bi].right.web_cut_angle)))), ((col_list[bi].depth/2) + 1.0), 0.0)

            ptWP2 = col_list[bi].right.location + col_list[bi].translate\

                    (-(col_list[bi].right.setback + flange_setback + (col_list[bi].tf-0.001)*tan(dtor(prep_angle)) -\

                     (((col_list[bi].depth/2) - col_list[bi].tf + .001)*tan(dtor(col_list[bi].right.web_cut_angle)))), (col_list[bi].depth/2), 0.0)

            ptWP3 = ptWP2 + col_list[bi].translate(((col_list[bi].tf+0.001)*tan(dtor(prep_angle))), -(col_list[bi].tf+0.001), 0.0)

            ptWP4 = ptWP3 + col_list[bi].translate(-flush_upper_right, 0.0, 0.0)

            ptWP5 = ptWP4 + col_list[bi].translate(-access_hole_length, -0.375, 0.0)

            ptWP6 = ptWP5 + col_list[bi].translate(0.0, -(access_hole_height - 0.375), 0.0)

            ptWP7 = col_list[bi].right.location + col_list[bi].translate\

                    (-(col_list[bi].right.setback - 1.0 - (((col_list[bi].depth/2))*tan(dtor(col_list[bi].right.web_cut_angle)))),\

                     (col_list[bi].depth/2) - (col_list[bi].tf + access_hole_height + 0.001), 0.0)

            ptWP8 = ptWP7 + col_list[bi].translate(0.0, +(col_list[bi].tf + access_hole_height + 0.001) + 1.0, 0.0)

            flange_prep_flush(col_list[bi], ptWP1, ptWP2, ptWP3, ptWP4, ptWP5, ptWP6, ptWP7, ptWP8, access_hole_radius)

        if "TOP End Bott Flg" in prep_list:

            ptWP1 = col_list[bi].right.location + col_list[bi].translate\

                    (-(col_list[bi].right.setback + flange_setback + (col_list[bi].tf+0.999)*tan(dtor(prep_angle)) -\

                     (((col_list[bi].depth/2) - col_list[bi].tf + .001)*tan(dtor(col_list[bi].right.web_cut_angle)))), -((col_list[bi].depth/2) + 1.0), 0.0)

            ptWP2 = col_list[bi].right.location + col_list[bi].translate\

                    (-(col_list[bi].right.setback + flange_setback + (col_list[bi].tf-0.001)*tan(dtor(prep_angle)) -\

                     (((col_list[bi].depth/2) - col_list[bi].tf + .001)*tan(dtor(col_list[bi].right.web_cut_angle)))), -(col_list[bi].depth/2), 0.0)

            ptWP3 = ptWP2 + col_list[bi].translate((col_list[bi].tf+0.001)*tan(dtor(prep_angle)), (col_list[bi].tf+0.001), 0.0)

            ptWP4 = ptWP3 + col_list[bi].translate(-flush_lower_right, 0.0, 0.0)

            ptWP5 = ptWP4 + col_list[bi].translate(-access_hole_length, 0.375, 0.0)

            ptWP6 = ptWP5 + col_list[bi].translate(0.0, (access_hole_height - 0.375), 0.0)

            ptWP7 = col_list[bi].right.location + col_list[bi].translate\

                    (-(col_list[bi].right.setback - 1.0 - (((col_list[bi].depth/2))*tan(dtor(col_list[bi].right.web_cut_angle)))),\

                     -(col_list[bi].depth/2) + (col_list[bi].tf + access_hole_height + 0.001), 0.0)

            ptWP8 = ptWP7 + col_list[bi].translate(0.0, -(col_list[bi].tf + access_hole_height + 0.001) - 1.0, 0.0)

            flange_prep_flush(col_list[bi], ptWP1, ptWP2, ptWP3, ptWP4, ptWP5, ptWP6, ptWP7, ptWP8, access_hole_radius)

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

    if Add_safety == 0:

        break

# end script