def __init__(self, point1 = None, point2 = None, slab = None):
# Huaicai 4/23/05: added some comments below to help understand the code.
# convert from 2d (x, y) coordinates into its 3d world (x, y, 0)
#coordinates(the lower-left and upper-right corner).
#In another word, the 3d coordinates minus the z offset of the plane
x = dot(A(point1), A(point2))
# Get the vector from upper-right point to the lower-left point
dx = subtract.reduce(x)
# Get the upper-left and lower right corner points
oc = x + V(point2*dot(dx,point2),
# Get the four 3d cooridinates on the bottom crystal-cutting plane
sq1 = cat(x,oc) + slab.normal*dot(slab.point, slab.normal)
# transfer the above 4 3d coordinates in parallel to get that on
#the top plane, put them together
sq1 = cat(sq1, sq1+slab.thickness*slab.normal)
self.data = V(maximum.reduce(sq1), minimum.reduce(sq1))
# just 2 3d points
self.data = V(maximum(point1, point2), minimum(point1, point2))
# list of points: could be 2d or 3d? +/- 1.8 to make the bounding
#box enclose the vDw ball of an atom?
self.data = V(maximum.reduce(point1) + BBOX_MARGIN,
minimum.reduce(point1) - BBOX_MARGIN)
# a null bbox
self.data = None
def selection_polyhedron(basepos, borderwidth = 1.8):
Given basepos (a Numeric array of 3d positions), compute and return (as a list of vertices, each pair being an edge to draw)
a simple bounding polyhedron, convenient for designating the approximate extent of this set of points.
(This is used on the array of atom and open bond positions in a chunk to designate a selected chunk.)
Make every face farther out than it needs to be to enclose all points in basepos, by borderwidth (default 1.8).
Negative values of borderwidth might sometimes work, but are likely to fail drastically if the polyhedron is too small.
The orientation of the faces matches the coordinate axes used in basepos (in typical calls, these are chunk-relative).
[#e Someday we might permit caller-specified orientation axes. The axes of inertia would be interesting to try.]
#bruce 060226/060605 made borderwidth an argument (non-default values untested); documented retval format
#bruce 060119 split this out of shakedown_poly_evals_evecs_axis() in chunk.py.
# Note, it has always had some bad bugs for certain cases, like long diagonal rods.
if not len(basepos):
return  # a guess
# find extrema in many directions
xtab = dot(basepos, polyXmat)
mins = minimum.reduce(xtab) - borderwidth
maxs = maximum.reduce(xtab) + borderwidth
polyhedron = makePolyList(cat(maxs,mins))
# apparently polyhedron is just a long list of vertices [v0,v1,v2,v3,...] to be passed to GL_LINES
# (via drawlinelist), which will divide them into pairs and draw lines v0-v1, v2-v3, etc.
# Maybe we should generalize the format, so some callers could also draw faces.
# [bruce 060226/060605 comment]
"""This function should be called after all properties of a material
have been updated. It will create the alpha chanel of the diffuse
component from the opacity property. It will return 1 if there are
alpha values < 1.0 or 0 else"""
difflen = self.prop[self.diff].shape
opaclen = self.prop[self.opac].shape
if self.binding[self.opac] == viewerConst.PER_VERTEX and difflen == 1 and opaclen >1:
# PER_VERTEX bindig && one color ( len(diffuse) == 1) && len(opacity vector) > 1:
# create diffuse vector which length is equal to len(opacity). Set the alpha
# chanel of this vector to the values from the opacity vector.
opac = self.prop[self.opac]
diff = ones( (opaclen,4), 'f')
diff[:,:3] = self.prop[self.diff][:3]
diff[:,3] = opac
self.prop[self.diff] = diff
elif self.binding[self.opac] == viewerConst.OVERALL or \
# OVERALL binding OR different length of diffuse and opacity vectors:
# set the alpha channel of the diffuse component to the first value of
# the opacity vector
diff = self.prop[self.diff]
opac = self.prop[self.opac]
alpha = ones( (diff.shape) )*float(opac)
diff[:,3] = alpha.astype('f')
self.prop[self.diff][:,3] = self.prop[self.opac][:]
# raise ValueError("diffuse/opacity property shape mismatch")
alphaMin = minimum.reduce( self.prop[self.opac] )
if alphaMin < 1.0: return 1
else: return 0
def add(self, point):
vl = cat(self.data, point)
self.data = V(maximum.reduce(vl), minimum.reduce(vl))