#!/bin/env python """ vec3.py: Used for managing vectors of lenght three. """ __author__ = "Christopher M. Bruns" __version__ = "1.0" import sys import simtk.unit class Vec3(object): """ Vec3 represents a three-dimensional point or displacement in space. Examples >>> v = Vec3((1, 2, 3)) >>> print v.dot(v) 14 >>> print abs(v) 3.74165738677 >>> v += Vec3((3,2,1)) >>> print v [4, 4, 4] >>> print v**2 48.0 >>> print v**1 6.92820323028 >>> print v [4, 4, 4] """ def __init__(self, xyz): """ Create a new Vec3 object, specifying its three elements. Examples: >>> v = Vec3((1,2,3)) >>> print v [1, 2, 3] """ x = xyz[0] y = xyz[1] z = xyz[2] self.data = [x, y, z] def __repr__(self): """ Create a string containing a python code representation of this Vec3. Examples >>> v = Vec3([1,2,3]) >>> v Vec3([1, 2, 3]) """ return self.__class__.__name__ + \ '([' + repr(self[0]) + ", " + repr(self[1]) + ", " + repr(self[2]) + '])' def __len__(self): """ Returns the number of elements in this Vec3. Always 3. Examples >>> v = Vec3((1, 2, 3)) >>> len(v) 3 """ return 3 def __iter__(self): """ Examples >>> v = Vec3((1,2,3)) >>> for c in v: ... print c ... 1 2 3 """ for coord in self.data: yield coord def __getitem__(self, key): return self.data[key] def __setitem__(self, key, value): self.data[key] = value def __abs__(self): return pow(self.dot(self), 0.5) def __neg__(self): return self.__class__([-self[0], -self[1], -self[2]]) def __pos__(self): return self def __add__(self, other): return self.__class__([self[0] + other[0], self[1] + other[1], self[2] + other[2]]) def __radd__(self, other): return self.__class__([other[0] + self[0], other[1] + self[1], other[2] + self[2]]) def __sub__(self, other): return self.__class__([self[0] - other[0], self[1] - other[1], self[2] - other[2]]) def __rsub__(self, other): return self.__class__([other[0] - self[0], other[1] - self[1], other[2] - self[2]]) def __mul__(self, other): """ Returns NotImplemented if the right hand side is a simtk.unit.Unit, so the Unit class can return a proper Quantity unit. Example >>> import simtk.unit >>> Vec3([1,2,3]) * simtk.unit.meter Quantity(Vec3([1, 2, 3]), meter) """ # If other is a Unit, delegate to Unit.__rmul__ multiplication if simtk.unit.is_unit(other): return NotImplemented return self.__class__([self[0] * other, self[1] * other, self[2] * other]) def __rmul__(self, other): return self.__class__([other * self[0], other * self[1], other * self[2]]) def __div__(self, other): # If other is a Unit, delegate to Unit.__rmul__ multiplication if simtk.unit.is_unit(other): return NotImplemented return self.__class__([self[0] / other, self[1] / other, self[2] / other]) def __rdiv__(self, other): return self.__class__([other / self[0], other / self[1], other / self[2]]) def __str__(self): return "["+str(self[0])+", "+str(self[1])+", "+str(self[2])+"]" def __pow__(self, exponent): return pow(self.dot(self), exponent * 0.5) def dot(self, other): assert len(other) == 3 return self[0] * other[0] + self[1] * other[1] + self[2] * other[2] # run module directly for testing if __name__=='__main__': # Test the examples in the docstrings import doctest, sys doctest.testmod(sys.modules[__name__])