Source code for sierra.core.vector

# Copyright 2020 John Harwell, All rights reserved.
#
#  SPDX-License-Identifier: MIT
"""
Representation of vectors in 3D space and operations on them..
"""
# Core packages
import math
import typing as tp

# 3rd party packages

# Project packages


[docs]class Vector3D: """Represents a point in 3D space and/or a directional vector in 3D space. """
[docs] @staticmethod def from_str(s: str, astype=int) -> 'Vector3D': return Vector3D(*tuple(map(astype, s.split(','))))
[docs] @staticmethod def d2norm(lhs: 'Vector3D', rhs: 'Vector3D') -> float: return math.sqrt((lhs.x - rhs.x) ** 2 + (lhs.y - rhs.y) ** 2)
[docs] def __init__(self, x=0, y=0, z=0): self.x = x self.y = y self.z = z
[docs] def __eq__(self, other: object) -> bool: if not isinstance(other, Vector3D): raise NotImplementedError return self.x == other.x and self.y == other.y and self.z == other.z
[docs] def __hash__(self) -> int: return hash((self.x, self.y, self.z))
[docs] def __len__(self) -> int: return int(self.length())
[docs] def __add__(self, o: 'Vector3D') -> 'Vector3D': return Vector3D((self.x + o.x), (self.y + o.y), (self.z + o.z))
[docs] def __sub__(self, o: 'Vector3D') -> 'Vector3D': return Vector3D((self.x - o.x), (self.y - o.y), (self.z - o.z))
[docs] def __mul__(self, o: tp.Union[float, int]) -> 'Vector3D': return Vector3D(self.x * o, self.y * o, self.z * o)
[docs] def __truediv__(self, o: tp.Union[float, int]) -> 'Vector3D': if isinstance(o, (float, int)): return Vector3D((self.x / o), (self.y / o), (self.z / o)) else: raise NotImplementedError
[docs] def __iadd__(self, o: 'Vector3D') -> 'Vector3D': self.x += o.x self.y += o.y self.z += o.z return self
[docs] def __isub__(self, o: 'Vector3D') -> 'Vector3D': self.x -= o.x self.y -= o.y self.z -= o.z return self
[docs] def __ge__(self, other: 'Vector3D') -> bool: return self.x >= other.x and self.y >= other.y and self.z >= other.z
[docs] def __le__(self, other: 'Vector3D') -> bool: return self.x <= other.x and self.y <= other.y and self.z <= other.z
[docs] def __lt__(self, other: 'Vector3D') -> bool: """ Determine if one vector is less than another by coordinate comparison. """ return ((self.x < other.x) or ((self.x == other.x) and (self.y < other.y)) or ((self.x == other.x) and (self.y == other.y) and (self.z < other.z)))
[docs] def __neg__(self) -> 'Vector3D': return Vector3D(-self.x, -self.y, -self.z)
[docs] def __str__(self) -> str: return self.__repr__()
[docs] def __repr__(self) -> str: return f'({self.x},{self.y},{self.z})'
[docs] def length(self) -> float: return math.sqrt((self.x * self.x) + (self.y * self.y) + (self.z * self.z))
[docs] def cross(self, rhs: 'Vector3D') -> 'Vector3D': return Vector3D(self.y * rhs.z - self.z * rhs.y, self.z * rhs.x - self.x * rhs.z, self.x * rhs.y - self.y * rhs.x)
[docs] def dot(self, rhs: 'Vector3D') -> 'Vector3D': return self.x * rhs.x + self.y * rhs.y + self.z * rhs.z
[docs] def normalize(self) -> 'Vector3D': length = self.length() self.x /= length self.y /= length self.z /= length return self
[docs] def perpendicularize(self: 'Vector3D') -> 'Vector3D': # From # https://math.stackexchange.com/questions/137362/how-to-find-perpendicular-vector-to-another-vector choice1 = Vector3D(0, self.z, -self.y) choice2 = Vector3D(-self.z, 0, self.x) choice3 = Vector3D(-self.y, self.x, 0) m = max([choice1, choice2, choice3], key=lambda v: v.length()) return m
__api__ = ['Vector3D']