Source code for pyuff_ustb.objects.point
from typing import TYPE_CHECKING, Tuple, Union
import numpy as np
from pyuff_ustb.objects.uff import Uff, compulsory_property, dependent_property
from pyuff_ustb.readers import read_scalar
if TYPE_CHECKING:
# Make sure properties are treated as properties when type checking
compulsory_property = property
optional_property = property
dependent_property = property
[docs]
class Point(Uff):
""":class:`Uff` class to define a point location.
:class:`Point` contains the position of a point in a tridimensional space. It
express that location in spherical coordinates which allows to place points at
infinity but in a given direction.
Original authors:
Alfonso Rodriguez-Molares (alfonso.r.molares@ntnu.no)
"""
# Compulsory properties
@compulsory_property
def distance(self) -> float:
"Distance from the point location to the origin of coordinates [m]"
if "distance" in self._reader:
return read_scalar(self._reader["distance"])
return 0.0
@compulsory_property
def azimuth(self) -> float:
"Angle from the point location to the plane YZ [rad]"
if "azimuth" in self._reader:
return read_scalar(self._reader["azimuth"])
return 0.0
@compulsory_property
def elevation(self) -> float:
"Angle from the point location to the plane XZ [rad]"
if "elevation" in self._reader:
return read_scalar(self._reader["elevation"])
return 0.0
# Dependent properties
@dependent_property
def xyz(self) -> np.ndarray:
"location of the point [m m m] if the point is not at infinity"
return np.array([self.x, self.y, self.z])
@dependent_property
def x(self) -> float:
return self.distance * np.sin(self.azimuth) * np.cos(self.elevation)
@dependent_property
def y(self) -> float:
return self.distance * np.sin(self.elevation)
@dependent_property
def z(self) -> float:
return self.distance * np.cos(self.azimuth) * np.cos(self.elevation)
# Some helpers for "writing" to dependent properties
@xyz.setter
def xyz(self, values: Union[Tuple[int, int, int], np.ndarray]):
if len(values) != 3:
raise ValueError("Must provide x, y, and z.")
x, y, z = values
self.distance = np.sqrt(x**2 + y**2 + z**2)
self.azimuth = np.arctan2(x, z)
if self.distance > 0:
if np.isinf(y):
self.elevation = np.pi / 2 * np.sign(y)
else:
self.elevation = np.arcsin(y / self.distance)
else:
self.elevation = 0
@x.setter
def x(self, value: float):
self.distance = np.sqrt(value**2 + self.y**2 + self.z**2)
self.azimuth = np.arctan2(value, self.z)
if self.distance > 0:
self.elevation = np.arcsin(self.y / self.distance)
else:
self.elevation = 0
@y.setter
def y(self, value: float):
self.distance = np.sqrt(self.x**2 + value**2 + self.z**2)
if self.distance > 0:
self.elevation = np.arcsin(value / self.distance)
else:
self.elevation = 0
@z.setter
def z(self, value: float):
self.distance = np.sqrt(self.x**2 + self.y**2 + value**2)
self.azimuth = np.arctan2(self.x, value)
if self.distance > 0:
self.elevation = np.arcsin(self.y / self.distance)
else:
self.elevation = 0