def plane(coords, findBounds=False): """Compute a plane given an Nx3 Numpy array. Returns a Plane whose origin is the centroid of the coords. If 'findBounds' is True, returns an additional Point (the furthest point projected into plane) and an additional floating-point number (distance from origin to that point). Tip: you generally generate the input Numpy array with numpyArrayFromAtoms() """ import numpy from numpy.linalg import eig, svd, eigh centroid = coords.mean(0) centered = coords - centroid ignore, vals, vecs = svd(centered) normal = vecs[numpy.argmin(vals)] from chimera import Point, Plane, Vector origin = Point(*centroid) plane = Plane(origin, Vector(*normal)) if findBounds: maxSqDist = None for coord in coords: projected = plane.nearest(Point(*coord)) sqDist = origin.sqdistance(projected) if maxSqDist == None or sqDist > maxSqDist: maxSqDist = sqDist furthest = projected from math import sqrt return plane, projected, sqrt(maxSqDist) return plane
def pointDistances(self, target): if isinstance(target, chimera.Point): points = [target] else: points = target from chimera import cross, Plane dists = [] minExt = min(self.extents) maxExt = max(self.extents) xfCenter = self.xformCenter() xfDirection = self.xformDirection() minPt = xfCenter + xfDirection * minExt maxPt = xfCenter + xfDirection * maxExt for pt in points: v = pt - xfCenter c1 = cross(v, xfDirection) if c1.length == 0.0: # colinear inPlane = pt else: plane = Plane(xfCenter, cross(c1, xfDirection)) inPlane = plane.nearest(pt) ptExt = (inPlane - xfCenter) * xfDirection if ptExt < minExt: measurePt = minPt elif ptExt > maxExt: measurePt = maxPt else: measurePt = inPlane dists.append(pt.distance(measurePt)) return dists