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.

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

"""

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

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

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