OpenMPCD
Vector3DReal.py
1 import math
2 
3 class Vector3DReal:
4  """
5  Represents a three-dimensional vector with the entries being real numbers.
6  """
7 
8  def __init__(self, x, y = None, z = None):
9  """
10  The constructor.
11 
12  @throw TypeError
13  Throws if the types of the arguments do not match the
14  specification.
15 
16  @param[in] x
17  This parameter may be an instance of `Vector3DReal`, in which
18  case this instance will be constructed to contain the same
19  elements as `x`, and it will be required that `y` and `z` be
20  `None`.
21  Alternatively, `x` may be a list or tuple of length `3`, with
22  each element being either an `int` or a `float`; the element
23  `0` will be taken as the `x` value for this vector, the
24  element `1` as `y`, and the element `2` as `z`. In this case,
25  too, `y` and `z` must be `None`.
26  Alternatively, `x` may be an `int` or `float` and will serve
27  as the `x` value for this instance. In this case, `y` and `z`
28  must be set likewise.
29  @param[in] y
30  Either `None` or the `y` value for this vector; see the
31  documentation of `x`.
32  @param[in] z
33  Either `None` or the `z` value for this vector; see the
34  documentation of `x`.
35  """
36 
37  if isinstance(x, Vector3DReal):
38  if y is not None or z is not None:
39  raise TypeError()
40 
41  self.x = x.x
42  self.y = x.y
43  self.z = x.z
44  return
45 
46  allowedTypes = (int, float)
47 
48  if isinstance(x, (list, tuple)):
49  if y is not None or z is not None:
50  raise TypeError()
51 
52  if len(x) != 3:
53  raise TypeError()
54 
55  for i in [0, 1, 2]:
56  if not isinstance(x[i], allowedTypes):
57  raise TypeError()
58 
59  self.x = x[0]
60  self.y = x[1]
61  self.z = x[2]
62  return
63 
64 
65  for var in [x, y, z]:
66  if not isinstance(var, allowedTypes):
67  raise TypeError()
68 
69  self.x = x
70  self.y = y
71  self.z = z
72 
73 
74  def getX(self):
75  """
76  Returns the `x` value.
77  """
78 
79  return self.x
80 
81 
82  def getY(self):
83  """
84  Returns the `y` value.
85  """
86 
87  return self.y
88 
89 
90  def getZ(self):
91  """
92  Returns the `z` value.
93  """
94 
95  return self.z
96 
97 
98  def dot(self, rhs):
99  """
100  Returns the dot product of this vector with `rhs`.
101 
102  @param[in] rhs
103  The right-hand-side instance, which must be of type
104  `Vector3DReal`.
105  """
106 
107  self._assertIsSameType(rhs)
108 
109  return self.x * rhs.x + self.y * rhs.y + self.z * rhs.z
110 
111 
112  def cross(self, rhs):
113  """
114  Returns the cross product of this vector with `rhs`.
115 
116  @param[in] rhs
117  The right-hand-side instance, which must be of type
118  `Vector3DReal`.
119  """
120 
121  self._assertIsSameType(rhs)
122 
123  cx = self.y * rhs.z - self.z * rhs.y;
124  cy = self.z * rhs.x - self.x * rhs.z;
125  cz = self.x * rhs.y - self.y * rhs.x;
126  return Vector3DReal(cx, cy, cz)
127 
128 
129  def getLengthSquared(self):
130  """
131  Returns the square of the length of this vector.
132  """
133 
134  return self.dot(self)
135 
136 
137  def getLength(self):
138  """
139  Returns the length of this vector.
140  """
141 
142  return math.sqrt(self.getLengthSquared())
143 
144 
145  def getNormalized(self):
146  """
147  Returns this vector, but normalized, i.e. divided by its length.
148 
149  @throw ValueError
150  Throws if `getLengthSquared() == 0`.
151  """
152 
153  if self.getLengthSquared() == 0:
154  raise ValueError()
155 
156  factor = 1.0 / self.getLength()
157  return Vector3DReal(self.x * factor, self.y * factor, self.z * factor)
158 
159  def normalize(self):
160  """
161  Normalizes this vector, i.e. divides it by its length.
162 
163  @throw ValueError
164  Throws if `getLengthSquared() == 0`.
165  """
166 
167  if self.getLengthSquared() == 0:
168  raise ValueError()
169 
170  factor = 1.0 / self.getLength()
171  self.x = self.x * factor
172  self.y = self.y * factor
173  self.z = self.z * factor
174 
175 
176  def getProjectionOnto(self, rhs):
177  """
178  Returns the projection of this vector onto the direction `rhs`.
179 
180  @throw ValueError
181  Throws if `rhs.getLengthSquared() == 0`.
182 
183  @param[in] rhs
184  The right-hand-side instance, which must be of type
185  `Vector3DReal` and must not be of zero length.
186  """
187 
188  self._assertIsSameType(rhs)
189 
190  if rhs.getLengthSquared() == 0:
191  raise ValueError()
192 
193  normalized = rhs.getNormalized()
194  return normalized * normalized.dot(self)
195 
196 
197  def getPerpendicularTo(self, rhs):
198  """
199  Returns the component of this vector that is perpendicular to `rhs`.
200 
201  @throw ValueError
202  Throws if `rhs.getLengthSquared() == 0`.
203 
204  @param[in] rhs
205  The right-hand-side instance, which must be of type
206  `Vector3DReal` and must not be of zero length.
207  """
208 
209  self._assertIsSameType(rhs)
210 
211  if rhs.getLengthSquared() == 0:
212  raise ValueError()
213 
214  return self -self.getProjectionOnto(rhs)
215 
216 
217  def getRotatedAroundNormalizedAxis(self, axis, angle):
218  """
219  Returns the this vector, rotated around the normalized vector `axis` by
220  `angle` radians in counter-clockwise direction.
221 
222  @throw ValueError
223  Throws if `axis.getLengthSquared() == 0`.
224 
225  @param[in] axis
226  The vector to rotate about, which must be of type
227  `Vector3DReal` and is assumed to be of unit length.
228  @param[in] angle
229  The amount to rotate, in radians.
230  """
231 
232  self._assertIsSameType(axis)
233 
234  if axis.getLengthSquared() == 0:
235  raise ValueError()
236 
237  thisDotAxis = self.dot(axis)
238  axisCrossThis = axis.cross(self)
239  projectionOntoAxis = axis * thisDotAxis
240  return \
241  projectionOntoAxis + \
242  (self -projectionOntoAxis) * math.cos(angle) + \
243  axisCrossThis * math.sin(angle)
244 
245 
246  def rotateAroundNormalizedAxis(self, axis, angle):
247  """
248  Sets this vector to be the result of `getRotatedAroundNormalizedAxis`,
249  called with the given arguments.
250 
251  @throw ValueError
252  Throws if `axis.getLengthSquared() == 0`.
253 
254  @param[in] axis
255  The vector to rotate about, which must be of type
256  `Vector3DReal` and is assumed to be of unit length.
257  @param[in] angle
258  The amount to rotate, in radians.
259  """
260 
261  self._assertIsSameType(axis)
262 
263  rotated = self.getRotatedAroundNormalizedAxis(axis, angle)
264  self.x = rotated.x
265  self.y = rotated.y
266  self.z = rotated.z
267 
268 
269  def isClose(self, rhs, relativeTolerance = None, absoluteTolerance = None):
270  """
271  Returns whether this instance and `rhs` are close to each other.
272 
273  Two vectors are "close" in this sense if all of their components are
274  close in the sense of `numpy.allclose`.
275 
276  @throw TypeError
277  Throws if any of the arguments have an invalid type.
278  @throw ValueError
279  Throws if any of the arguments have an invalid value.
280 
281  @param[in] rhs
282  The other instance of `Vector3DReal` to compare to.
283  @param[in] relativeTolerance
284  A non-negative `float` that is passed as the `rtol` parameter
285  of `numpy.allclose`, or `None` for its default value.
286  @param[in] absoluteTolerance
287  A non-negative `float` that is passed as the `atol` parameter
288  of `numpy.allclose`, or `None` for its default value.
289  """
290 
291  self._assertIsSameType(rhs)
292 
293  for x in [relativeTolerance, absoluteTolerance]:
294  if not isinstance(x, (float, type(None))):
295  raise TypeError()
296  if x is not None and x < 0:
297  raise ValueError
298 
299 
300  a = [self.x, self.y, self.z]
301  b = [rhs.x, rhs.y, rhs.z]
302  kwargs = {}
303  if relativeTolerance is not None:
304  kwargs["rtol"] = relativeTolerance
305  if absoluteTolerance is not None:
306  kwargs["atol"] = absoluteTolerance
307 
308  import numpy
309  return numpy.allclose(a, b, **kwargs)
310 
311 
312  def __eq__(self, rhs):
313  """
314  Returns `True` if `rhs` contains the same entries as this instance, and
315  `False` otherwise.
316 
317  @param[in] rhs
318  The right-hand-side instance, which must be of type
319  `Vector3DReal`.
320  """
321 
322  self._assertIsSameType(rhs)
323 
324  if self.x != rhs.x:
325  return False
326  if self.y != rhs.y:
327  return False
328  if self.z != rhs.z:
329  return False
330  return True
331 
332 
333  def __ne__(self, rhs):
334  """
335  Returns the negation of `__eq__`.
336 
337  @param[in] rhs
338  The right-hand-side instance, which must be of type
339  `Vector3DReal`.
340  """
341 
342  return not self.__eq__(rhs)
343 
344 
345  def __add__(self, rhs):
346  """
347  Returns the sum of this instance and `rhs`.
348 
349  @param[in] rhs
350  The right-hand-side instance, which must be of type
351  `Vector3DReal`.
352  """
353 
354  self._assertIsSameType(rhs)
355 
356  return Vector3DReal(self.x + rhs.x, self.y + rhs.y, self.z + rhs.z)
357 
358 
359  def __sub__(self, rhs):
360  """
361  Returns the difference of this instance and `rhs`.
362 
363  @param[in] rhs
364  The right-hand-side instance, which must be of type
365  `Vector3DReal`.
366  """
367 
368  self._assertIsSameType(rhs)
369 
370  return Vector3DReal(self.x - rhs.x, self.y - rhs.y, self.z - rhs.z)
371 
372 
373  def __mul__(self, rhs):
374  """
375  Returns the product of this instance and `rhs`.
376 
377  @param[in] rhs
378  The factor to multiply with, which must be either of type
379  `int` or `float`.
380  """
381 
382  allowedTypes = (int, float)
383  if not isinstance(rhs, allowedTypes):
384  raise TypeError()
385 
386  return Vector3DReal(self.x * rhs, self.y * rhs, self.z * rhs)
387 
388 
389  def __div__(self, rhs):
390  """
391  Returns the ratio of this instance and `rhs`.
392 
393  The division performed is always a floating-point division.
394 
395  @param[in] rhs
396  The factor to divide by with, which must be either of type
397  `int` or `float`, and must not be `0`.
398  """
399 
400  return self.__truediv__(rhs)
401 
402 
403  def __truediv__(self, rhs):
404  """
405  Returns the ratio of this instance and `rhs`.
406 
407  The division performed is always a floating-point division.
408 
409  @param[in] rhs
410  The factor to divide by with, which must be either of type
411  `int` or `float`, and must not be `0`.
412  """
413 
414  allowedTypes = (int, float)
415  if not isinstance(rhs, allowedTypes):
416  raise TypeError()
417 
418  if rhs == 0:
419  raise ValueError()
420 
421  if isinstance(rhs, int):
422  rhs = float(rhs)
423 
424  return Vector3DReal(self.x / rhs, self.y / rhs, self.z / rhs)
425 
426 
427  def __neg__(self):
428  """
429  Returns the negative of this vector.
430  """
431 
432  return Vector3DReal(-self.x, -self.y, -self.z)
433 
434 
435  def __getitem__(self, index):
436  """
437  Returns the coordinate with the given index.
438 
439  @param[in] index
440  The coordinate index, which must be `0` for the `x`
441  coordinate, `1` for `y`, or `2` for `z`.
442  """
443 
444  if index == 0:
445  return self.getX()
446 
447  if index == 1:
448  return self.getY()
449 
450  if index == 2:
451  return self.getZ()
452 
453  raise KeyError()
454 
455 
456  def __repr__(self):
457  """
458  Returns a string representation of this instance.
459  """
460 
461  return "(" + str(self.x) + ", " + str(self.y) + ", " + str(self.z) + ")"
462 
463 
464  def _assertIsSameType(self, value):
465  """
466  Throws `TypeError` if `value` is not of type `Vector3DReal`.
467 
468  @param[in] value
469  The value to check.
470  """
471 
472  if not isinstance(value, Vector3DReal):
473  raise TypeError()
MPCDAnalysis.Vector3DReal.Vector3DReal.__init__
def __init__(self, x, y=None, z=None)
Definition: Vector3DReal.py:37
MPCDAnalysis.Vector3DReal.Vector3DReal.__ne__
def __ne__(self, rhs)
Definition: Vector3DReal.py:358
MPCDAnalysis.Vector3DReal.Vector3DReal.y
y
Definition: Vector3DReal.py:44
MPCDAnalysis.Vector3DReal.Vector3DReal.getX
def getX(self)
Definition: Vector3DReal.py:80
MPCDAnalysis.Vector3DReal.Vector3DReal.__sub__
def __sub__(self, rhs)
Definition: Vector3DReal.py:386
MPCDAnalysis.Vector3DReal.Vector3DReal.dot
def dot(self, rhs)
Definition: Vector3DReal.py:111
MPCDAnalysis.Vector3DReal.Vector3DReal.getRotatedAroundNormalizedAxis
def getRotatedAroundNormalizedAxis(self, axis, angle)
Definition: Vector3DReal.py:244
MPCDAnalysis.Vector3DReal.Vector3DReal.isClose
def isClose(self, rhs, relativeTolerance=None, absoluteTolerance=None)
Definition: Vector3DReal.py:305
MPCDAnalysis.Vector3DReal.Vector3DReal.getLength
def getLength(self)
Definition: Vector3DReal.py:149
MPCDAnalysis.Vector3DReal.Vector3DReal.__mul__
def __mul__(self, rhs)
Definition: Vector3DReal.py:401
MPCDAnalysis.Vector3DReal.Vector3DReal.getPerpendicularTo
def getPerpendicularTo(self, rhs)
Definition: Vector3DReal.py:220
MPCDAnalysis.Vector3DReal.Vector3DReal.__div__
def __div__(self, rhs)
Definition: Vector3DReal.py:420
MPCDAnalysis.Vector3DReal.Vector3DReal.__getitem__
def __getitem__(self, index)
Definition: Vector3DReal.py:467
MPCDAnalysis.Vector3DReal.Vector3DReal.__eq__
def __eq__(self, rhs)
Definition: Vector3DReal.py:337
MPCDAnalysis.Vector3DReal.Vector3DReal.cross
def cross(self, rhs)
Definition: Vector3DReal.py:126
MPCDAnalysis.Vector3DReal.Vector3DReal.getProjectionOnto
def getProjectionOnto(self, rhs)
Definition: Vector3DReal.py:198
MPCDAnalysis.Vector3DReal.Vector3DReal
Definition: Vector3DReal.py:7
MPCDAnalysis.Vector3DReal.Vector3DReal.getLengthSquared
def getLengthSquared(self)
Definition: Vector3DReal.py:140
MPCDAnalysis.Vector3DReal.Vector3DReal.__repr__
def __repr__(self)
Definition: Vector3DReal.py:485
MPCDAnalysis.Vector3DReal.Vector3DReal.rotateAroundNormalizedAxis
def rotateAroundNormalizedAxis(self, axis, angle)
Definition: Vector3DReal.py:274
MPCDAnalysis.Vector3DReal.Vector3DReal.getNormalized
def getNormalized(self)
Definition: Vector3DReal.py:161
MPCDAnalysis.Vector3DReal.Vector3DReal.getZ
def getZ(self)
Definition: Vector3DReal.py:98
MPCDAnalysis.Vector3DReal.Vector3DReal.normalize
def normalize(self)
Definition: Vector3DReal.py:176
MPCDAnalysis.Vector3DReal.Vector3DReal.getY
def getY(self)
Definition: Vector3DReal.py:89
MPCDAnalysis.Vector3DReal.Vector3DReal.x
x
Definition: Vector3DReal.py:43
MPCDAnalysis.Vector3DReal.Vector3DReal.z
z
Definition: Vector3DReal.py:45
MPCDAnalysis.Vector3DReal.Vector3DReal.__add__
def __add__(self, rhs)
Definition: Vector3DReal.py:371
MPCDAnalysis.Vector3DReal.Vector3DReal.__neg__
def __neg__(self)
Definition: Vector3DReal.py:454
MPCDAnalysis.Vector3DReal.Vector3DReal._assertIsSameType
def _assertIsSameType(self, value)
Definition: Vector3DReal.py:497
MPCDAnalysis.Vector3DReal.Vector3DReal.__truediv__
def __truediv__(self, rhs)
Definition: Vector3DReal.py:435