## EllipseLayout.py Version 1.00
## Copyright (c) 2006
## All rights
reserved.
############################################################################
"""
Revision History:
Version 1.00 (
Version 1.01 (11/12/06) - Removed print
statements used for debugging
Removed 'z'
adjustment factor since 3D translations are made using
material
coordinates instead of member coordinates
Select three points in your current plane
in a counter-clockwise direction:
1. The ellipse center point (Point 1)
2. A point representing an axis end
point in the ellipse 'x' direction (Point 2)
From this point the 'x' semi-axis
default dimension and default ellipse rotation is calculated.
3. Any point in the current plane that
is not collinear with the other two (Point 3)
From this point the ellipse 'y'
semi-axis default dimension is calculated.
The third point should be picked
counter-clockwise with respect to the other two points.
Three non-collinear points are
required to define a plane.
Dialog box selections:
1. The quadrant to layout the ellipse
(one quadrant is laid out at a time)
2. Number of layout spaces between
points (ellipse resolution)
3. Axis dimensions and rotation
Algorithim:
Add a miscellaneous member representing
the unit vector of the defined plane (WP)
Divide the quadrant (90 degrees) by
resolution
Resolution rays originate at member WP
(0,0,0) (Point 1)
Calculate member WP -z (ellipse x) and
y (ellipse y) coordinates of the intersection of each
resolution ray with the ellipse
Rotate each calculated point about
member WP by the rotation angle of the ellipse
Add miscellaneous member at each
rotated resolution point (RP)
"""
def
run_script():
import macrolib.pickle
from macrolib.FileDefaults
import import_data, export_data,
data_Defaults_path
from macrolib.angle
import rtod, dtor
from macrolib.P3D import Plane3D
from macrolib.PointRotate
import PointRotate3D
from math import atan2, tan, cos, sin, pi
from param import
yes_or_no, ResponseNotOK,
Units, Dialog, dim_print, Warning, dim
import os
import sys
Units("feet")
from point import Point, PointLocate
from member import Member
from cons_line
import ConsLine
# from rnd_bar
import RndBar
#######################################################
## Variables Section
# system path for default values files
# auto save path
default_file_path
= data_Defaults_path()
# default values file name
def_file =
"EllipseLayout_v1_01.txt"
# default to enable or disable the
automatic importing and exporting of dialog dictionary variables
# ("Enable", "Disable")
enable_default_import_export
= "Enable"
image_path = os.path.join(os.getcwd(),
"macro", "Images")
image_name1 = os.path.join(image_path, "EllipseLayout1.gif")
image_name2 = os.path.join(image_path, "EllipseLayout2.gif")
## Defaults Section
resEllipse = 6
quadEllipse =
"0-90" #
("0-90", "90-180", "180-270",
"270-360")
"""
# Default values are calculated from user
input:
axis1Ellipse
axis2Ellipse
rotEllipse
"""
#######################################################
def add_RP(pt1,
pt2, mk=""):
# cannot assign existing =
"Yes"
# cannot assign sequence to
miscellaneous member
# description is ignored
memadd1 = Member('Misc
Round Bar')
memadd1.piecemark = mk
memadd1.left.location = pt1
memadd1.right.location = pt2
memadd1.grade = "A36"
memadd1.centered = "Yes"
memadd1.bar_diameter = 1
memadd1.work_pt_dist = 1.0
memadd1.mtrl_type = "Round bar"
memadd1.finish = "None"
# memadd1.existing = "Yes"
memadd1.description = "Ref
Point"
memadd1.ref_pt_offset = (0, 0, 0)
memadd1.add()
return memadd1
#######################################################
while 1:
# Auto import default values file
if enable_default_import_export
== "Enable":
dd1 = import_data(os.path.join(default_file_path, def_file))
if dd1:
for key, value in dd1.items():
exec "%s = %s" %
(key, repr(value)) in None
else:
Warning("Invalid data or
defaults file does not exist - Reverting to original defaults")
###################################################
ptWP = PointLocate ("Pick the ellipse center point ")
ptAxis = PointLocate("Pick an ellipse 'X' direction axis
WP")
ptPlane = PointLocate("Pick another point counter-clockwise to
define the current plane")
if None not in (ptWP,
ptAxis, ptPlane):
# create class instance 'a'
a = Plane3D(ptWP,
ptAxis, ptPlane)
# add ellipse center WP
mem1 = add_RP(ptWP, ptWP + a.N_uv,
"WP")
# calculate rotation of ellipse
with respect to mem1.main_mtrl()
ptTem =
mem1.main_mtrl().to_local(ptAxis
- ptWP)
if round(ptTem.z,
4) == 0.0:
if ptTem.y
> 0.0:
rotEllipse
= pi/2
else:
rotEllipse
= -pi/2
else:
rotEllipse
= atan2(ptTem.y, -ptTem.z)
###############################################################
##
DIALOG BOX 1 ---------------------------------------------#
###############################################################
dlg1 = Dialog("Ellipse
Layout")
dlg1.menu("print_doc",
("Yes", "No"), "No", "Print parametric
script documentation only ")
dlg1.tabset_begin()
dlg1.tab("General
Information")
dlg1.group_title("Additional
Ellipse Information")
dlg1.entry("axis1Ellipse", dim_print(ptWP.dist(ptAxis)), "Ellipse
semi-axis dimension 'X'
")
dlg1.entry("axis2Ellipse", dim_print(ptWP.dist(ptPlane)),
"Ellipse semi-axis dimension 'Y'")
dlg1.entry("resEllipse", resEllipse,
"Ellipse resolution")
dlg1.menu("quadEllipse",
("0-90", "90-180", "180-270",
"270-360"), quadEllipse, "Ellipse
quadrant")
dlg1.entry("rotEllipse", rtod(rotEllipse), "Ellipse rotation with respect to current
plane")
dlg1.tab("Image 1")
dlg1.group_title("Ellipse laid
out in plane of beam top flange")
dlg1.image(image_name1)
dlg1.tab("Image 2")
dlg1.group_title("Five 3 point
construction circles approximate the ellipse")
dlg1.image(image_name2)
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
------------------------------------------#
###############################################################
rotEllipse
= dtor(rotEllipse)
if print_doc
== "Yes":
print __doc__
break
# Auto export default values to
disk if enabled
if enable_default_import_export
== "Enable":
export_data(os.path.join(default_file_path, def_file), dd1)
"""
Calculate points along ellipse
in mem1.main_mtrl() coordinates before rotating
Equation of an ellipse: (x**2/b**2) +
(y**2/h**2) = 1
Equation of resolution ray: mx-y = 0 where m = tan(A)
Substituting and solving for
'x': x=(b**2*h**2/(h**2+b*m**2))**0.5
Solving for 'y': y=(((b**2*h**2)-(h**2*x**2))/b**2)**0.5
"""
# initialize local point list
localRP_list
= []
rayIncrement
= (pi/2.0)/resEllipse
for i in
range(resEllipse + 1):
xAxis =
axis1Ellipse # b
yAxis
= axis2Ellipse # h
xOff
= (xAxis**2*yAxis**2/(yAxis**2+(xAxis*tan(rayIncrement * (i)))**2))**0.5
yOff
= (((xAxis**2*yAxis**2)-(yAxis**2*xOff**2))/xAxis**2)**0.5
localRP_list.append(Point(0.0,
yOff, -xOff))
if quadEllipse
== "90-180":
for pt in localRP_list:
pt.z
= -pt.z
elif quadEllipse == "180-270":
for pt in localRP_list:
pt.y
= -pt.y
pt.z
= -pt.z
elif quadEllipse == "270-360":
for pt in localRP_list:
pt.y
= -pt.y
else: # quadEllipse
== "0-90", do nothing
pass
# rotate points into position
# initialize a new list to store
rotated points
localRP_rot
= []
for pt in localRP_list:
localRP_rot.append(PointRotate3D(Point(0.0,
0.0, 0.0), Point(1.0, 0.0, 0.0), pt, rotEllipse))
for pt in localRP_rot:
pt1 = ptWP
+ mem1.main_mtrl().translate(pt.x, pt.y, pt.z)
add_RP(pt1,
pt1 + a.N_uv, "RP")
if not yes_or_no("Layout
another ellipse quadrant?"):
break
##
End run_script()
#################################################
if
__name__ == '__main__':
try:
run_script()
finally:
del run_script