Spaces:
Runtime error
Runtime error
| import numpy as np | |
| from pymo.Quaternions import Quaternions | |
| class Pivots: | |
| """ | |
| Pivots is an ndarray of angular rotations | |
| This wrapper provides some functions for | |
| working with pivots. | |
| These are particularly useful as a number | |
| of atomic operations (such as adding or | |
| subtracting) cannot be achieved using | |
| the standard arithmatic and need to be | |
| defined differently to work correctly | |
| """ | |
| def __init__(self, ps): | |
| self.ps = np.array(ps) | |
| def __str__(self): | |
| return "Pivots(" + str(self.ps) + ")" | |
| def __repr__(self): | |
| return "Pivots(" + repr(self.ps) + ")" | |
| def __add__(self, other): | |
| return Pivots(np.arctan2(np.sin(self.ps + other.ps), np.cos(self.ps + other.ps))) | |
| def __sub__(self, other): | |
| return Pivots(np.arctan2(np.sin(self.ps - other.ps), np.cos(self.ps - other.ps))) | |
| def __mul__(self, other): | |
| return Pivots(self.ps * other.ps) | |
| def __div__(self, other): | |
| return Pivots(self.ps / other.ps) | |
| def __mod__(self, other): | |
| return Pivots(self.ps % other.ps) | |
| def __pow__(self, other): | |
| return Pivots(self.ps**other.ps) | |
| def __lt__(self, other): | |
| return self.ps < other.ps | |
| def __le__(self, other): | |
| return self.ps <= other.ps | |
| def __eq__(self, other): | |
| return self.ps == other.ps | |
| def __ne__(self, other): | |
| return self.ps != other.ps | |
| def __ge__(self, other): | |
| return self.ps >= other.ps | |
| def __gt__(self, other): | |
| return self.ps > other.ps | |
| def __abs__(self): | |
| return Pivots(abs(self.ps)) | |
| def __neg__(self): | |
| return Pivots(-self.ps) | |
| def __iter__(self): | |
| return iter(self.ps) | |
| def __len__(self): | |
| return len(self.ps) | |
| def __getitem__(self, k): | |
| return Pivots(self.ps[k]) | |
| def __setitem__(self, k, v): | |
| self.ps[k] = v.ps | |
| def _ellipsis(self): | |
| return tuple(map(lambda x: slice(None), self.shape)) | |
| def quaternions(self, plane="xz"): | |
| fa = self._ellipsis() | |
| axises = np.ones(self.ps.shape + (3,)) | |
| axises[fa + ("xyz".index(plane[0]),)] = 0.0 | |
| axises[fa + ("xyz".index(plane[1]),)] = 0.0 | |
| return Quaternions.from_angle_axis(self.ps, axises) | |
| def directions(self, plane="xz"): | |
| dirs = np.zeros((len(self.ps), 3)) | |
| dirs["xyz".index(plane[0])] = np.sin(self.ps) | |
| dirs["xyz".index(plane[1])] = np.cos(self.ps) | |
| return dirs | |
| def normalized(self): | |
| xs = np.copy(self.ps) | |
| while np.any(xs > np.pi): | |
| xs[xs > np.pi] = xs[xs > np.pi] - 2 * np.pi | |
| while np.any(xs < -np.pi): | |
| xs[xs < -np.pi] = xs[xs < -np.pi] + 2 * np.pi | |
| return Pivots(xs) | |
| def interpolate(self, ws): | |
| dir = np.average(self.directions, weights=ws, axis=0) | |
| return np.arctan2(dir[2], dir[0]) | |
| def copy(self): | |
| return Pivots(np.copy(self.ps)) | |
| def shape(self): | |
| return self.ps.shape | |
| def from_quaternions(cls, qs, forward="z", plane="xz"): | |
| ds = np.zeros(qs.shape + (3,)) | |
| ds[..., "xyz".index(forward)] = 1.0 | |
| return Pivots.from_directions(qs * ds, plane=plane) | |
| def from_directions(cls, ds, plane="xz"): | |
| ys = ds[..., "xyz".index(plane[0])] | |
| xs = ds[..., "xyz".index(plane[1])] | |
| return Pivots(np.arctan2(ys, xs)) | |