def __init__(self, point1=None, point2=None, slab=None): # Huaicai 4/23/05: added some comments below to help understand the code. if slab: # 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[1] + V(point2[0] * dot(dx, point2[0]), point2[1] * dot(dx, point2[1])) # 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)) elif point2: # just 2 3d points self.data = V(maximum(point1, point2), minimum(point1, point2)) elif point1: # 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) else: # a null bbox self.data = None
def __init__(self, point1 = None, point2 = None, slab = None): # Huaicai 4/23/05: added some comments below to help understand the code. if slab: # 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[1] + V(point2[0]*dot(dx,point2[0]), point2[1]*dot(dx,point2[1])) # Get the four 3d cooridinates on the bottom cookie-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)) elif point2: # just 2 3d points self.data = V(maximum(point1, point2), minimum(point1, point2)) elif point1: # 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) else: # 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] return polyhedron
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] return polyhedron
def add(self, point): vl = cat(self.data, point) self.data = V(maximum.reduce(vl), minimum.reduce(vl))
# == helper definitions for selection_polyhedron [moved here from drawer.py by bruce 060119] # mat mult by rowvector list and max/min reduce to find extrema D = math.sqrt(2.0) / 2.0 T = math.sqrt(3.0) / 3.0 # 0 1 2 3 4 5 6 7 8 9 10 11 12 # 13 14 15 16 17 18 19 20 21 22 23 24 25 polyXmat = A([[1, 0, 0, D, D, D, D, 0, 0, T, T, T, T], [0, 1, 0, D, -D, 0, 0, D, D, T, T, -T, -T], [0, 0, 1, 0, 0, D, -D, D, -D, T, -T, T, -T]]) del D, T polyMat = cat(transpose(polyXmat), transpose(polyXmat)) polyTab = [ (9, (0, 7, 3), [3, 0, 5, 2, 7, 1, 3]), (10, (0, 1, 4), [3, 1, 8, 15, 6, 0, 3]), #(10, (0,4,1), [3,0,6,15,8,1,3]), (11, (8, 11, 7), [4, 14, 21, 2, 5, 0, 4]), (12, (8, 4, 9), [4, 0, 6, 15, 20, 14, 4]), (22, (5, 10, 9), [18, 13, 16, 14, 20, 15, 18]), (23, (10, 6, 11), [16, 13, 19, 2, 21, 14, 16]), (24, (1, 2, 5), [8, 1, 17, 13, 18, 15, 8]), (25, (3, 6, 2), [7, 2, 19, 13, 17, 1, 7]) ] #( 9, (0,7,3), [3,0,5,2,7,1,3]), #(10, (0,1,4), [3,1,8,15,6,0,3]), #(11, (8,11,7), [4,14,21,2,5,0,4]), #(12, (8,4,9), [4,0,6,15,20,14,4]),
return polyhedron # == helper definitions for selection_polyhedron [moved here from drawer.py by bruce 060119] # mat mult by rowvector list and max/min reduce to find extrema D = math.sqrt(2.0)/2.0 T = math.sqrt(3.0)/3.0 # 0 1 2 3 4 5 6 7 8 9 10 11 12 # 13 14 15 16 17 18 19 20 21 22 23 24 25 polyXmat = A([[1, 0, 0, D, D, D, D, 0, 0, T, T, T, T], [0, 1, 0, D, -D, 0, 0, D, D, T, T, -T, -T], [0, 0, 1, 0, 0, D, -D, D, -D, T, -T, T, -T]]) del D, T polyMat = cat(transpose(polyXmat),transpose(polyXmat)) polyTab = [( 9, (0,7,3), [3,0,5,2,7,1,3]), (10, (0,1,4), [3,1,8,15,6,0,3]),#(10, (0,4,1), [3,0,6,15,8,1,3]), (11, (8,11,7), [4,14,21,2,5,0,4]), (12, (8,4,9), [4,0,6,15,20,14,4]), (22, (5,10,9), [18,13,16,14,20,15,18]), (23, (10,6,11), [16,13,19,2,21,14,16]), (24, (1,2,5), [8,1,17,13,18,15,8]), (25, (3,6,2), [7,2,19,13,17,1,7])] #( 9, (0,7,3), [3,0,5,2,7,1,3]), #(10, (0,1,4), [3,1,8,15,6,0,3]), #(11, (8,11,7), [4,14,21,2,5,0,4]), #(12, (8,4,9), [4,0,6,15,20,14,4]), #(22, (5,10,9), [18,13,16,14,20,15,18]), #(23, (10,6,11), [16,13,19,2,21,14,16]),