## Walls_v2.00.py

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

## All rights reserved.

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

"""

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

****This version will only work in SDS/2 versions 7.111 and higher****

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

 

Select a series of CLOCKWISE points representing miscellaneous member lines.

Select whether the member lines represent the outside, inside, or center of the wall.

A series of rectangular plate miscellaneous members are added and miter fitted.

The ends of the material will be extended by the wall thickness for mitering.

The first and last material ends in a series will not be extended if the start

and end points are at different locations.

User must be in plan.

The member line is at the top or bottom of wall elevation.

 

*** Sequence was added to the dialog box in version 1.02

    As a temporary workaround, asterisks will prefix and suffix an integer sequence

    in the dialog box. The asterisks will be stripped automatically.

*** Updated in Version 2.00 - Job().sequences() method eliminates the need for the

    previous workaround.

 

Version History:

Version 1.00 (2/7/07) -     Initial release

Version 1.01 (2/8/07) -     Pass material fit miter is material list contains only one object

                            Add option for member line to be at bottom of wall

Version 1.02 (8/31/07) -    Move startup code outside run_script()

                            Fix import P3D error

                            Add sequence to dialog box

Version 2.00 (12/6/07) -    Add point argument in PointLocate for rubber band

                            Incorporate Job().sequences() method

"""

# startup code begin

from macrolib.P3D import Plane3D

from macrolib.Basis3D import BasisTransToGlobal

from macrolib.FileDefaults import import_data, export_data

from macrolib.PrintPtList import formatPtList

from macrolib.angle import rtod, dtor, planRotPts

from macrolib.AngleBetMemTrue import trueAngleBetweenMembers as tA

import os

from member import Member

from job import Job

from param import yes_or_no, Dialog, dim_print, ResponseNotOK

from point import Point, PointLocate

from rect_plate import RectPlate

from math import pi, tan

from mtrl_fit import MtrlFit

# startup code end

def run_script():

   

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

    ## Variables section

    # system path for defaults file

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

    # default values file

    def_file = "Walls_v2_00.txt"

    # no images in this version

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

    # default to enable or disable the importing and exporting of

    # dialog dictionary variables "Enable" "Disable"

    enable_default_import_export = "Enable"

    seq = '24'

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

    ## Defaults Section

    # ['Outside', 'Inside', 'Center']   

    wall_ref = 'Inside'

 

    wall_thk = 8.0

 

    elev_top_of_wall = -8.0

 

    elev_bott_of_wall = -56.0

   

    ['Top', 'Bott']

    bott_or_top = 'Bott'   

 

    ## End Variables and Defaults #############

    def miter_dist(x):

        return tan(x - x/2)

   

    def add_misc_rect_plate(p1, p2, width, thk, setLeft=0.0, setRight=0.0, ref='NS', rot=0.0, bt='Top', seq='25'):

        if bt == 'Top':

            xrot = 90.0

        else:

            xrot = -90.0

           

        if rot > pi/2 or rot <= -pi/2:

            zrot = 180.0

        else:

            zrot = 0.0

           

        # member begin

        memadd5 = Member('Misc Rectangular Plate')

        memadd5.left.location = p1

        memadd5.right.location = p2

        memadd5.grade = Job().steel_grades("Plate").keys()[0]

        memadd5.origin = ref

        memadd5.width = width

        memadd5.thick = thk

        memadd5.work_pt_dist = p1.dist(p2)

        memadd5.setback_left = setLeft

        memadd5.setback_right = setRight

        memadd5.length = memadd5.work_pt_dist - memadd5.setback_left - memadd5.setback_right

        memadd5.length = p1.dist(p2)

        memadd5.mtrl_type = 'Plate'

        memadd5.mtrl_usage = "Wall"

        # Has no effect

        memadd5.finish = "None"

        # Has no effect

        memadd5.color = (100, 100, 100)

        memadd5.description = "Exist Wall"

        memadd5.sequence = seq

        memadd5.ref_pt_offset = (0.0, 0.0, 0.0)

        memadd5.add()

        memadd5.rotate((xrot, 0.0, zrot))

       

        # member end

        return memadd5

 

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

    # if enabled, import defaults used previously from disk file

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

        pt_list = []

        while True:

            if pt_list:

                pt = PointLocate('Pick a wall corner point or return', pt)

            else:               

                pt = PointLocate('Pick a wall corner point or return')

            if pt is None:

                break

            else:

                pt_list.append(pt)

 

        if len(pt_list) > 1:

            # Sequence may be converted to integer upon import

            seq = str(seq)

          

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

            dlg1 = Dialog("Walls")

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

            dlg1.group_title('Wall options')

            dlg1.menu("wall_ref", ['Inside', 'Outside', 'Center'], wall_ref, 'Member line relationship to material')

            dlg1.menu("bott_or_top", ['Top', 'Bott'], bott_or_top, 'Member line at TOP or BOTT of wall')

            dlg1.entry("wall_thk", dim_print(wall_thk), "Wall thickness")

            dlg1.entry('elev_top_of_wall', dim_print(elev_top_of_wall), 'Top of wall elevation')

            dlg1.entry('elev_bott_of_wall', dim_print(elev_bott_of_wall), 'Bottom of wall elevation')

            dlg1.group_title('Sequence')

            dlg1.menu('seq', Job().sequences(), seq, 'Select sequence')

           

            try:

                dd1 = dlg1.done()

            except ResponseNotOK:

                break

           

            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)

 

            if bott_or_top == 'Top':

                if wall_ref == 'Inside':

                    ref = 'NS'

                elif wall_ref == 'Outside':

                    ref = 'FS'

                elif wall_ref == 'Center':

                    ref = 'Center'

                   

                z_ref = elev_top_of_wall

               

            else:

                if wall_ref == 'Inside':

                    ref = 'FS'

                elif wall_ref == 'Outside':

                    ref = 'NS'

                elif wall_ref == 'Center':

                    ref = 'Center'

                   

                z_ref = elev_bott_of_wall

 

            mtrl_list = []

            wall_width = elev_top_of_wall - elev_bott_of_wall               

 

            extend_str1 = '-wall_thk * miter_dist(tA(pt_list[i-2], pt_last, pt_last, pt))'

            extend_str2 = '-wall_thk * miter_dist(tA(pt_last, pt, pt, pt_list[i+1]))'      

           

            if wall_width > 0.0:

                if pt_list[0].dist(pt_list[-1]) < 1:

                    end_off1 = '-wall_thk * miter_dist(tA(pt_last, pt, pt_list[-2], pt_list[-1]))'

                    end_off2 = '-wall_thk * miter_dist(tA(pt_last, pt, pt_list[0], pt_list[1]))'

                else:

                    end_off1 = '0.0'

                    end_off2 = '0.0'

 

                for pt in pt_list:

                        pt.z = z_ref                   

 

                for i, pt in enumerate(pt_list):

                    # print i

                    # First point

                    if i == 0:

                        # print 'Option 1'

                        pt_last = pt

 

                    # Second point, two points selected                       

                    elif i == 1 and len(pt_list) == 2:

                        # print 'Option 2'

                        # Calculate member plan rotation

                        # If plan rotation is in the range > 90 <= -90

                        #   rotate about 'z' axis 180 deg

                        m = add_misc_rect_plate(pt_last, pt, wall_width, wall_thk, 0.0, 0.0, ref, planRotPts(pt_last, pt), bott_or_top, seq)

                        mtrl_list.append(m)

                        pt_last = pt

 

                    # Second point

                    elif i == 1:

                        # print 'Option 3'

                        off1, off2 = eval(end_off1), eval(extend_str2)

                        m = add_misc_rect_plate(pt_last, pt, wall_width, wall_thk, off1, off2, ref, planRotPts(pt_last, pt), bott_or_top, str(seq))

                        mtrl_list.append(m)

                        pt_last = pt

 

                    # Third point or more and last line segment   

                    elif i > 1 and i == len(pt_list)-1:

                        # print 'Option 4'

                        off1, off2 = eval(extend_str1), eval(end_off2)

                        m = add_misc_rect_plate(pt_last, pt, wall_width, wall_thk, off1, off2, ref, planRotPts(pt_last, pt), bott_or_top, str(seq))

                        mtrl_list.append(m)                       

                        pt_last = pt

 

                    # Third point or more and NOT last line segment                 

                    elif i > 1 and i < len(pt_list)-1:

                        # print 'Option 5'

                        off1, off2 = eval(extend_str1), eval(extend_str2)

                        m = add_misc_rect_plate(pt_last, pt, wall_width, wall_thk, off1, off2, ref, planRotPts(pt_last, pt), bott_or_top, str(seq))

                        mtrl_list.append(m)                       

                        pt_last = pt

                       

                    else:

                        print 'No option available'

                        pass

 

                # Miter fit wall materials if the material list contains 2 or more objects

                if len(mtrl_list) > 1:

                    # mtrl fit begin

                    mfit1 = MtrlFit()

                    mfit1.mtrl = mtrl_list

                    mfit1.frame_type = "Field weld"

                    mfit1.clear = 0

                    mfit1.show_window = "No"

                    mfit1.fit("Mitre")

                    # mtrl fit end

            else:

                print 'You have entered a negative wall width!'

                break

                   

        if not yes_or_no("Add more walls?"):

            break

                  

## End run_script()

if __name__ == '__main__':

    try:

        run_script()

    finally:

        del run_script