"""mesh building block - Coord class definition"""
import os
from typing import Tuple, Any
if os.environ.get('__USE_CUDA', '0') == '1':
import cupy as np
from cupy import ndarray
else:
import numpy as np
from numpy import ndarray
from g3d.defs import G3DWorld
from g3d.defs import AngleType
from g3d.defs import G3DEntity
from g3d.defs import FunctionByPass
[docs]
class Coord(G3DEntity):
def __init__(self, *args: Any, **kwargs: Any) -> None:
self._spacing = -1
self._ialt = AngleType.UNDEFINED
self._alpha = 0.
self._beta = 0.
self._shape_factor = None
self._angle_dim = AngleType.DEGREES
self._x = 0.
self._y = 0.
self._z = 0.
super().__init__(*args, **kwargs)
def _set_default(self) -> None:
super()._set_default()
self._tag = 'g3d_coord'
self.set_coordinates(0., 0., 0.)
def _set_from_args(self, *args: Any, **kwargs: Any) -> ndarray:
bps = self._get_function_evaluate_status(**kwargs)
if bps is FunctionByPass.SELF:
args_stat = np.ones(len(args))
else:
args_stat = super()._set_from_args(*args)
if bps in [FunctionByPass.EVALUATE, FunctionByPass.SELF]:
if np.sum(args_stat) > 0:
coord_data = []
for i in range(len(args)):
if args_stat[i] == 1:
arg = args[i]
if type(arg) is Coord:
# if caught by a super class, the child class instance of copy will be used
args_stat[i] = 0
self.copy_coordinates(arg)
for key, value in kwargs.items():
if key == 'copy_settings':
if value:
# copy settings from Coord
self.copy_settings(arg)
elif type(arg) in [float, np.float64, np.float32, int, np.int64, np.int32]:
args_stat[i] = 0
coord_data.append(np.float64(arg))
elif type(arg) is list:
args_stat[i] = 0
if self._list_is_all_floats(arg) and len(arg) > 0:
self._x = arg[0]
if len(arg) > 1:
self._y = arg[1]
if len(arg) > 2:
self._z = arg[2]
else:
print(arg, type(arg))
if len(coord_data) > 0:
# will be caught by the for-loop below in a sub call to _set_from_args
self._set_from_args(coord_data, bps=FunctionByPass.SELF)
return args_stat
[docs]
def set_coordinates(self, xs: float, ys: float, zs: float) -> None:
"""
:param xs:
:param ys:
:param zs:
"""
self._x = xs
self._y = ys
self._z = zs
[docs]
def set_from_key_value(self, key: str, value: Any) -> bool:
if super().set_from_key_value(key, value):
return True
elif key == 'spacing':
self._spacing = value
return True
elif key == 'ialt':
self._ialt = value
return True
elif key == 'alpha':
self._alpha = value
return True
elif key == 'beta':
self._beta = value
return True
elif key == 'shape_factor':
self._shape_factor = value
return True
elif key == 'angle_dim':
self._angle_dim = value
return True
elif key == 'copy_settings':
return True
elif key == 'x':
self._x = value
return True
elif key == 'y':
self._y = value
return True
elif key == 'z':
self._z = value
return True
return False
@property
def x(self) -> float:
"""
:return:
"""
return self._x
@x.setter
def x(self, val: float) -> None:
self._x = val
@property
def y(self) -> float:
"""
:return:
"""
return self._y
@y.setter
def y(self, val: float) -> None:
self._y = val
@property
def z(self) -> float:
"""
:return:
"""
return self._z
@z.setter
def z(self, val: float) -> None:
self._z = val
@property
def spacing(self) -> float:
"""
:return:
"""
return self._spacing
@spacing.setter
def spacing(self, val: float) -> None:
self._spacing = val
@property
def ialt(self) -> Any:
"""
:return:
"""
return self._ialt
@ialt.setter
def ialt(self, val: Any) -> None:
if type(val) is AngleType:
self._ialt = val
@property
def alpha(self) -> float:
"""
:return:
"""
return self._alpha
@alpha.setter
def alpha(self, val: float) -> None:
self._alpha = val
@property
def beta(self) -> float:
"""
:return:
"""
return self._beta
@beta.setter
def beta(self, val: float) -> None:
self._beta = val
@property
def shape_factor(self) -> float:
"""
:return:
"""
return self._shape_factor
@shape_factor.setter
def shape_factor(self, val: float) -> None:
self._shape_factor = val
@property
def angle_dim(self) -> Any:
"""
:return:
"""
return self._angle_dim
@angle_dim.setter
def angle_dim(self, val: Any) -> None:
if type(val) is AngleType:
self._angle_dim = val
[docs]
def copy(self, c: 'Coord', **kwargs: Any) -> None:
self.copy_coordinates(c)
if len(kwargs) != 0:
g3d_world = G3DWorld()
for key, value in kwargs.items():
if g3d_world.display.verbose:
print('%s == %s' % (key, str(value)))
if key == 'copy_settings':
if value:
self.copy_settings(c)
else:
print('warning! parameter %s is not defined' % key)
[docs]
def copy_coordinates(self, c: 'Coord') -> None:
"""
:param c:
"""
self._x = c.x
self._y = c.y
self._z = c.z
[docs]
def copy_settings(self, c: 'Coord') -> None:
"""
:param c:
"""
super().copy(c)
self._spacing = c.spacing
self._ialt = c.ialt
self._alpha = c.alpha
self._beta = c.beta
self._shape_factor = c.shape_factor
self._angle_dim = c.angle_dim
[docs]
def subtract(self, c: 'Coord') -> 'Coord':
"""
:param c:
:return:
"""
self._x -= c.x
self._y -= c.y
self._z -= c.z
return self
[docs]
def add(self, c: 'Coord') -> 'Coord':
"""
:param c:
:return:
"""
self._x += c.x
self._y += c.y
self._z += c.z
return self
[docs]
def multiply(self, c: 'Coord') -> 'Coord':
"""
:param c:
:return:
"""
self._x *= c.x
self._y *= c.y
self._z *= c.z
return self
[docs]
def divide(self, c: 'Coord') -> 'Coord':
"""
:param c:
:return:
"""
self._x /= c.x
self._y /= c.y
self._z /= c.z
return self
[docs]
def length(self) -> float:
"""
:return:
"""
return np.sqrt(self._x ** 2 + self._y ** 2 + self._z ** 2)
[docs]
def scale(self, f: float) -> 'Coord':
"""
:param f:
:return:
"""
self._x *= f
self._y *= f
self._z *= f
return self
[docs]
def get_xyz(self) -> Tuple[float, float, float]:
"""
:return:
"""
return self._x, self._y, self._z
[docs]
def get_array(self) -> ndarray:
"""
:return:
"""
return np.array([self._x, self._y, self._z])
[docs]
def print(self, **kwargs: Any) -> None:
print_settings = False
for key, value in kwargs.items():
if key == 'print_settings':
print_settings = value
super().print()
print('coordinates:')
print(' [x, y, z] = [%f, %f, %f]' % (self._x, self._y, self._z))
if print_settings:
print('settings:')
print(' cell spacing: %f' % self._spacing)
print(' angle dimension: %s' % self._angle_dim.name)
if self._ialt == AngleType.IALT_1 or self._ialt == AngleType.IALT_2 or self._ialt == AngleType.IALT_3:
print(' ialt: %s' % self._ialt.name)
alpha = self._alpha
beta = self._beta
if self._angle_dim == AngleType.RADIANS:
alpha *= 180. / np.pi
beta *= 180. / np.pi
print(' alpha: %f degrees' % alpha)
print(' beta: %f degrees' % beta)
if self._shape_factor is not None:
print(' shape factor: %f' % float(self._shape_factor))
[docs]
def rotate(self, **kwargs: Any) -> None:
"""
:param kwargs:
:return:
"""
alpha = 0.
beta = 0.
gamma = 0.
angle_dim = AngleType.DEGREES
if len(kwargs) != 0:
g3d_world = G3DWorld()
for key, value in kwargs.items():
if g3d_world.display.verbose:
print('%s == %s' % (key, str(value)))
if key == 'alpha':
alpha = value
elif key == 'beta':
beta = value
elif key == 'gamma':
gamma = value
elif key == 'angle_dim':
angle_dim = value
else:
print('warning! parameter %s is not defined' % key)
if alpha == 0. and beta == 0. and gamma == 0.:
print('warning! no rotation angle specified')
return
if angle_dim == AngleType.DEGREES:
alpha *= np.pi / 180.
beta *= np.pi / 180.
gamma *= np.pi / 180.
eps = 1.e-6
csa = np.cos(alpha)
ssa = np.sin(alpha)
csb = np.cos(beta)
ssb = np.sin(beta)
csg = np.cos(gamma)
ssg = np.sin(gamma)
if np.abs(alpha) > eps:
yy = self._y
zz = self._z
self._y = csa * yy - ssa * zz
self._z = ssa * yy + csa * zz
if np.abs(beta) > eps:
xx = self._x
zz = self._z
self._z = csb * zz + ssb * xx
self._x = -ssb * zz + csb * xx
if np.abs(gamma) > eps:
xx = self._x
yy = self._y
self._x = csg * xx - ssg * yy
self._y = ssg * xx + csg * yy
[docs]
def shift(self, **kwargs: Any) -> None:
"""
:param kwargs:
:return:
"""
x_shift = 0.
y_shift = 0.
z_shift = 0.
if len(kwargs) != 0:
g3d_world = G3DWorld()
for key, value in kwargs.items():
if g3d_world.display.verbose:
print('%s == %s' % (key, str(value)))
if key == 'x_shift':
x_shift = value
elif key == 'y_shift':
y_shift = value
elif key == 'z_shift':
z_shift = value
else:
print('warning! parameter %s is not defined' % key)
if x_shift == 0. and y_shift == 0. and z_shift == 0.:
print('warning! no shift specified')
return
self._x += x_shift
self._y += y_shift
self._z += z_shift
[docs]
def get_delta(self, c: 'Coord') -> Tuple[float, float, float]:
"""
:param c:
:return:
"""
return c.x - self._x, c.y - self._y, c.z - self._z
[docs]
def get_dist(self, c: 'Coord') -> float:
"""
:param c:
:return:
"""
dx, dy, dz = self.get_delta(c)
return np.sqrt(dx ** 2 + dy ** 2 + dz ** 2)
[docs]
def get_angle(self, c: 'Coord', **kwargs: Any) -> Tuple[float, float]:
"""
:param c:
:param kwargs:
:return:
"""
# ialt=IALT_1
# alpha: angle between vector and x-axis
# beta: angle between projection of vector on yz-plane and y-axis (positive towards z-axis)
#
# ialt=IALT_2
# alpha: angle between vector and y-axis
# beta: angle between projection of vector on xz-plane and z-axis (positive towards x-axis)
#
# ialt=IALT_3
# alpha: angle between vector and z-axis
# beta: angle between projection of vector on xy-plane and x-axis (positive towards y-axis)
ialt = AngleType.IALT_1
angle_dim = AngleType.DEGREES
if len(kwargs) != 0:
g3d_world = G3DWorld()
for key, value in kwargs.items():
if g3d_world.display.verbose:
print('%s == %s' % (key, str(value)))
if key == 'ialt':
ialt = value
elif key == 'angle_dim':
angle_dim = value
else:
if key != 'direction':
print('warning! parameter %s is not defined' % key)
alpha = 0.
beta = 0.
dx, dy, dz = self.get_delta(c)
if ialt is AngleType.IALT_1:
beta = np.arctan2(dz, dy)
alpha = np.arctan2(dy / np.cos(beta), dx)
elif ialt is AngleType.IALT_2:
beta = np.arctan2(dx, dz)
alpha = np.arctan2(dz / np.cos(beta), dy)
elif ialt is AngleType.IALT_3:
beta = np.arctan2(dy, dx)
alpha = np.arctan2(dx / np.cos(beta), dz)
if angle_dim is AngleType.DEGREES:
alpha *= (180. / np.pi)
beta *= (180. / np.pi)
return alpha, beta
[docs]
def scatter_XY(self, plt: Any, m: str = 'o') -> None:
"""
:param plt:
:param m:
"""
plt.scatter(self._x, self._y, marker=m)
[docs]
def scatter_XZ(self, plt: Any, m: str = 'o') -> None:
"""
:param plt:
:param m:
"""
plt.scatter(self._x, self._z, marker=m)
[docs]
def scatter_YZ(self, plt: Any, m: str = 'o') -> None:
"""
:param plt:
:param m:
"""
plt.scatter(self._y, self._z, marker=m)