##PlaneConstArray3D.py Version 1.03

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

##All rights reserved.

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

"""

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

///                                 Modify while loop to add additional construction line patterns.

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

                    cl2.add()

                    # 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