Hole Array.py

 

Hole Face = 1, Points selected counter-clockwise, Slots are rotated

Strong axis roll

 

Hole Face 1, Points selected clockwise, Slots are rotated

Strong axis roll

 

Hole Face 1, Points selected clockwise, Slots are rotated

Strong axis roll

 

Hole Face 3, Points selected clockwise, Slots are aligned

Weak axis roll

 

## Hole_Array_v1.00.py

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

## All rights reserved.

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

"""

Add an array of holes to an existing piece of material.

Originally coded for angle material.

User must determine the hole face.

Holes and slots can be rotated perpendicular to the radial lines***.

***The selection order of points (clockwise vs. counter-clockwise) affects

   the slot rotation. The different possibilities have not been fully tested

   or implemented.

 

User input:

    Select the material

    Pick the array center point

    Pick the hole array start point on the gage line

    Pick the hole array end point

    Note that the 3 selected points must not be collinear

    Enter information into the dialog box

 

/// Revision History:

///     Version 1.00 (01/25/07) -   Initial release

///

///

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

///     P3D.py

///     pickle.py (required for FileDefaults)

///     FileDefaults.py

///     ExceptWarn.py

///     PolarPt.py

///     PrintPtList.py

///     angle.py

///     ptUtils.py

///

/// Go to 'Variables section to edit default values file path and file name

"""

def run_script():

    # startup code begin

    from macrolib.P3D import Plane3D

    from macrolib.FileDefaults import import_data, export_data

    from macrolib.ExceptWarn import formatExceptionInfo

    from macrolib.PolarPt import PolarPt3D

    from macrolib.PrintPtList import formatPtList

    from macrolib.angle import dtor, rtod

    from macrolib.ptUtils import uv, dot_product

    import types

    import os

    from math import floor, ceil, pi, sqrt, acos

    from param import yes_or_no, Dialog, dim_print

    from mtrl_list import MtrlLocate, HoleLocate

    from point import Point, PointLocate

    from hole_add import Hole

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

    # default values file

    def_file = "Hole_Array_v1_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"    

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

    ## Defaults Section

    #("Fixed Spacing", ) User enters the desired spacing between the holes along the arc

    spacing_method = "Fixed Spacing"

    fix_spa = 12.0

    min_start_dist = 3.0

    min_end_dist = 3.0

    # controls whether the holes/slots are rotated normal to the radial lines or aligned with the material axis

    # ['Align', 'Rotate']

    set_rotation = "Align"

    # bolt size

    bolt_size = 0.75                          

    # bolt type, Job().bolt_sched()

    bolt_type = "A325N"                    

    # hole type ("Standard Round", "Short Slot", "Oversized Round", "Long Slot")

    hole_type = "Long Slot"        

    # long slot length where applicable - enter 0" to have SDS/2 calculate length

    long_slot_length = 0.0

    hole_face = 1

    ## End variables and defaults section

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

    def hole_add(matl, pt, hltype, fa, bltsz, bltype, slot_len, rot):

        if slot_len:

            str = "slot_len"

        else:       

            str = "hole26.calc_slot_length()"

        try:

            # hole group add begin

            hole26 = Hole()

            hole26.mtrl = [matl, ]

            hole26.pt1 = pt

            hole26.hole_type = hltype

            hole26.face = fa

            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 = rot

            hole26.locate = "Center"

            hole26.columns = 1

            hole26.rows = 1

            hole26.bolt_type = bltype

            hole26.bolt_dia = bltsz

            hole26.slot_rot = 0.0

            hole26.length = eval(str)

            hole26.hole_dia = hole26.calc_hole_size()

            hole26.show_window = "Yes"

            hole26.create()

            # hole group add end

            return hole26

        except:

            Warning(formatExceptionInfo())

 

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

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

            else:

                Warning("Invalid data - Reverting to original defaults")

    ## Main program

    while 1:

        m1 = MtrlLocate("Select material to add array of holes", 'Single')

        pt1 = PointLocate("Pick center point of array")

        pt2 = PointLocate("Pick start point of array at radius")

        pt3 = PointLocate("Pick end point of array")

        if pt1 != None and pt2 != None and pt3 != None:

            a = Plane3D(pt1, pt2, pt3)

            if a.N_len > 0.0:

               

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

               

                dlg1 = Dialog("Hole Array")

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

                dlg1.group_title("The arc radius = %s and the arc length = %s." % (dim_print(a.Ra), dim_print(a.pp)))

                dlg1.menu("spacing_method", ("Fixed Spacing", ), spacing_method, "Layout Method                            ")

                dlg1.entry("fix_spa", dim_print(fix_spa), "C/C hole distance")

                dlg1.entry("min_start_dist", dim_print(min_start_dist), "Min dist from 1st point to first hole")

                dlg1.entry("min_end_dist", dim_print(min_end_dist), "Min dist from 2nd point to last hole")

                dlg1.menu("set_rotation", ['Align', 'Rotate'], set_rotation, "Rotate or Align holes")

                dlg1.group_title_end

 

                dlg1.group_title("Hole face - 1='Top Face'   2='Web NS'   3='Bottom Face'   4='Web FS'")

                dlg1.menu("hole_face", (1, 2, 3, 4), hole_face, "Hole face")

                dlg1.group_title_end

               

                dlg1.group_title("Hole information")

                dlg1.entry("bolt_size", dim_print(bolt_size), "Bolt size                ")

                dlg1.menu("bolt_type", Job().bolt_sched(), bolt_type, "Bolt type")

                dlg1.menu("hole_type", ("Standard Round", "Short Slot", "Oversized Round", "Long Slot"), hole_type, "Hole type")

                dlg1.entry("long_slot_length", dim_print(long_slot_length), "Long slot length (0 to calc.) where applicable")

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

 

                if enable_default_import_export == "Enable":

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

 

                allow_out_to_out = a.pp - min_start_dist - min_end_dist

                no_spa = int(floor(allow_out_to_out / fix_spa))

                actual_spa = fix_spa

                dst = min_start_dist + (allow_out_to_out/2) - (no_spa*fix_spa/2.0)

                no_spa = no_spa + 1

 

                pt_list = []

                if set_rotation == "Rotate":

                    # Determine angle between the material 'X' axis and the line connecting pt1 and pt2

                    # Angle in radians is the dot product of the unit vectors (pt2-pt1 dot m1.pt2-m1.pt1)

                    uv1 = uv(pt1, pt2)

                    uv2 = uv(m1.pt1 + m1.translate(m1.work_pt_dist, 0.0, 0.0), m1.pt1)

                    mtrl_angle = rtod(acos(dot_product(uv2, uv1)))+90.0

                    # print mtrl_angle

                    if mtrl_angle > 180.0:

                        mtrl_angle = (mtrl_angle-180.0)*-1

                        # print mtrl_angle

                   

                    # Compile a list of tuples (point, rotation) determined by the angle between holes

                    for i in range(no_spa):

                        pt_list.append((a.PointRotate3D(pt2, dst/a.Ra), rtod(dst/a.Ra)+mtrl_angle))

                        dst = dst + actual_spa

                else:

                    # Compile a list of tuples (point, rotation) determined by the angle between holes

                    for i in range(no_spa):

                        pt_list.append((a.PointRotate3D(pt2, dst/a.Ra), 0.0))

                        dst = dst + actual_spa

 

                for pt, rot in pt_list:

                    hole_add(m1, pt, hole_type, hole_face, bolt_size, bolt_type, long_slot_length, rot)

 

            else:

                Warning("The 3 points selected must not be collinear.")

               

        if not yes_or_no("Add another hole array?"):

            break

       

## end run_script() #########################################################

       

if __name__ == '__main__':

    try:

        run_script()

    finally:

        del run_script