def angle_between_vectors(v1, v2): """ Calculates the angle between <v1> and <v2>. The result is in the range [0, pi] On degenerate input (any of the vectors of norm 0) will raise ValueError. """ v1 = Vector(v1, copy=False) v2 = Vector(v2, copy=False) n1 = v1.norm() n2 = v2.norm() if n1 == 0 or n2 == 0: raise ValueError("Can't calculate angle between zero length vectors !") cos_a = v1.dot(v2) / (n1 * n2) cos_a = max(-1.0, min(1.0, cos_a)) return math.acos(cos_a)
class Ellipsoid(Primitive): def __init__(self, name, center, a, b, c, copy=False): Primitive.__init__(self, name=name) self.center = Vector(center, copy=copy) self.a = Vector(a, copy=copy) self.b = Vector(b, copy=copy) self.c = Vector(c, copy=copy) def __repr__(self): return "ELL(name={0}, center={1}, a={2}, b={3}, c={4})".format( self.name, repr(self.center), repr(self.a), repr(self.b), repr(self.c) ) def __iter__(self): yield self.center yield self.a yield self.b yield self.c def update_params(self, params): params.update({ "center": self.center, "a": self.a, "b": self.b, "c": self.c, }) def copy(self): return Ellipsoid(self.name, self.center, self.a, self.b, self.c, copy=True) def has_same_data(self, other): return all(map(Vector.is_same, self, other)) def _get_radius(self): """ Returns the radius if this is a Sphere, None otherwise. Can also be used as a test if this is a sphere: >>> x = Ellipsoid("test", "0, 0, 0", (10, 0, 0), [0, 10, 0], Vector("0, 0, 10")) >>> x.radius 10.0 >>> x.a = Vector("1, 0, 0") >>> x.radius is None True """ mag_a = self.a.norm() mag_b = self.b.norm() mag_c = self.c.norm() if np.allclose((mag_a, mag_b), (mag_b, mag_c)): return mag_a else: return None radius = property(_get_radius) @staticmethod def from_wdb(name, data): return Ellipsoid( name=name, center=data.v, a=data.a, b=data.b, c=data.c, )
class Ellipsoid(Primitive): def __init__(self, name, center, a, b, c, copy=False): Primitive.__init__(self, name=name) self.center = Vector(center, copy=copy) self.a = Vector(a, copy=copy) self.b = Vector(b, copy=copy) self.c = Vector(c, copy=copy) def __repr__(self): return "ELL(name={0}, center={1}, a={2}, b={3}, c={4})".format( self.name, repr(self.center), repr(self.a), repr(self.b), repr(self.c)) def __iter__(self): yield self.center yield self.a yield self.b yield self.c def update_params(self, params): params.update({ "center": self.center, "a": self.a, "b": self.b, "c": self.c, }) def copy(self): return Ellipsoid(self.name, self.center, self.a, self.b, self.c, copy=True) def has_same_data(self, other): return all(map(Vector.is_same, self, other)) def _get_radius(self): """ Returns the radius if this is a Sphere, None otherwise. Can also be used as a test if this is a sphere: >>> x = Ellipsoid("test", "0, 0, 0", (10, 0, 0), [0, 10, 0], Vector("0, 0, 10")) >>> x.radius 10.0 >>> x.a = Vector("1, 0, 0") >>> x.radius is None True """ mag_a = self.a.norm() mag_b = self.b.norm() mag_c = self.c.norm() if np.allclose((mag_a, mag_b), (mag_b, mag_c)): return mag_a else: return None radius = property(_get_radius) @staticmethod def from_wdb(name, data): return Ellipsoid( name=name, center=data.v, a=data.a, b=data.b, c=data.c, )