##PlaneConstArray3D.py Version 1.03

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

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

"""

/// Given 3 non-collinear points, define a plane and create a polar array of construction lines about

/// point 1 and between points 2 and 3.

/// User can be in any model orientation.

/// Developed by Bruce Vaughan, BV Detailing & Design, Inc. (October 2006)

/// URL: www.bvdetailing.com

/// Credit Paul Bourke for 'Rotate A Point About An Arbitrary Axis (3D)' (August 2002) and

/// 'Equation of a plane' (March 1989))

///

/// Revision History:

///     Version 1.01 (10/18/06) -   Instance method 'a.pr_init' no longer required - deleted

///                                 Module 'P3D' (version 1.01) incorporate optional argument for theta

///                                 Incorporate import/export default files

///                                 Add option to print documentation only

///     Version 1.02 (10/30/06) -   Create function run_script() to execute

///                                 Import functions import_data and export_data

///                                 Add construction line color variable

///     Version 1.03 (1/16/07) -    Import math.pi

///

///

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

///     P3D.py

///     pickle.py (required for P3D)

///     FileDefaults.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

import types

import os

from math import floor, ceil, pi

from param import yes_or_no, Dialog, dim_print

from member import Member, MemberLocate

from point import Point, PointLocate

from cons_line import ConsLine

from rnd_bar import RndBar

# 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 = "PlaneConstArray3D_v1_02.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

spacing_method = "Even Spacing"        #("Fixed Spacing", "Auto Spacing, "Even Spacing")

max_spa = 24.0

start_pt_dist = 12.0

end_pt_dist = 12.0

fix_spa = 24.0

min_start_dist = 12.0

min_end_dist = 12.0

no_spa = 8

cons_color = "Cyan"

## End variables and defaults section

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

# 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

else:

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

## Main program

while 1:

pick_180 = yes_or_no("Construction Line Array - Available options", \

"180 degree arc counter-clockwise",\

"180 degree arc clockwise",\

"Less than 180 degree arc"

)

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

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

if pick_180 == "180 degree arc counter-clockwise":

pt3 = PointLocate("Pick a reference point to define the current plane")

theta = pi

elif pick_180 == "180 degree arc clockwise":

pt3 = PointLocate("Pick a reference point to define the current plane")

theta = -pi

else:

pt3 = PointLocate("Pick array end point")

theta = 0.0

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

a = Plane3D(pt1, pt2, pt3, theta)

if a.N_len > 0.0:

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

dlg1 = Dialog("Construction Line Layout Options")

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

dlg1.group_title("General")

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

dlg1.menu("cons_color", ["White", "Red", "Yellow", "Green", "Cyan", "Blue", "Magenta"], cons_color, "Construction line color")

dlg1.line("All distances are measured along the arc.")

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

dlg1.group_title_end

dlg1.group_title("Fixed Spacing Options")

dlg1.entry("fix_spa", dim_print(fix_spa), "Fixed spacing dimension")

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

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

dlg1.group_title_end

dlg1.group_title("Auto Spacing Options")

dlg1.entry("max_spa", dim_print(max_spa), "Maximum spacing dimension")

dlg1.entry("start_pt_dist", dim_print(start_pt_dist), "Fixed dist from 1st point to first cons line")

dlg1.entry("end_pt_dist", dim_print(end_pt_dist), "Fixed dist from 2nd point to last cons line")

dlg1.group_title_end

dlg1.group_title("Even Spacing Options")

dlg1.entry("no_spa", no_spa, "Number of spaces")

dlg1.group_title_end

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)

pt_list = [pt2, ]

if spacing_method == "Fixed Spacing":

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

elif spacing_method == "Auto Spacing":

no_spa = int(ceil((a.pp - start_pt_dist - end_pt_dist) / max_spa))

actual_spa = (a.pp - start_pt_dist - end_pt_dist) / no_spa

dst = start_pt_dist

no_spa = no_spa + 1

elif spacing_method == "Even Spacing":

actual_spa = a.pp/no_spa

dst = actual_spa

no_spa = no_spa - 1

# Compile a list of points determined by the angle required between construction lines

for i in range(no_spa):

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

dst = dst + actual_spa

pt_list.append(a.PointRotate3D(pt2, a.Q))

for p in pt_list:

# construction line begin

cl2 = ConsLine()

cl2.pt1 = pt1

cl2.pt2 = p

cl2.pen = cons_color

# construction line end

else:

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

if not yes_or_no("Add more construction lines?"):

break

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

if __name__ == '__main__':

try:

run_script()

finally:

del run_script