Skip to content

Commit

Permalink
Implementing Line and Segment classes (#54)
Browse files Browse the repository at this point in the history
Co-authored-by: Maxime Rey <87315832+MaxJPRey@users.noreply.github.com>
Co-authored-by: Chad Queen <chadqueen82@gmail.com>
  • Loading branch information
3 people authored Sep 8, 2022
1 parent 204e038 commit da5dffd
Show file tree
Hide file tree
Showing 15 changed files with 1,150 additions and 211 deletions.
1 change: 1 addition & 0 deletions src/ansys/geometry/core/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import importlib_metadata

__version__ = importlib_metadata.version(__name__.replace(".", "-"))
"""The installed version of PyGeometry."""


# Units
Expand Down
12 changes: 12 additions & 0 deletions src/ansys/geometry/core/math/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,15 @@
"Vector2D",
"Vector3D",
]

UNIT_VECTOR_X = UnitVector3D([1, 0, 0])
"""Unit vector in the cartesian traditional X direction."""

UNIT_VECTOR_Y = UnitVector3D([0, 1, 0])
"""Unit vector in the cartesian traditional Y direction."""

UNIT_VECTOR_Z = UnitVector3D([0, 0, 1])
"""Unit vector in the cartesian traditional Z direction."""

ZERO_VECTOR3D = Vector3D([0, 0, 0])
"""Zero-valued Vector3D object."""
5 changes: 5 additions & 0 deletions src/ansys/geometry/core/math/point.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,11 @@ def unit(self, unit: Unit) -> None:
check_pint_unit_compatibility(unit, UNIT_LENGTH)
self._unit = unit

@property
def base_unit(self) -> Unit:
"""Returns the base unit of the object."""
return self._base_unit

def __eq__(self, other: "Point3D") -> bool:
"""Equals operator for ``Point3D``."""
check_type_equivalence(other, self)
Expand Down
44 changes: 35 additions & 9 deletions src/ansys/geometry/core/math/vector.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,15 +94,23 @@ def __ne__(self, other: "Vector3D") -> bool:
"""Not equals operator for ``Vector3D``."""
return not self == other

def __mul__(self, other: "Vector3D") -> Real:
"""Overload * operator with dot product."""
check_type_equivalence(other, self)
return self.dot(other)
def __mul__(self, other: Union["Vector3D", Real]) -> Union["Vector3D", Real]:
"""Overload * operator with dot product.
Note
----
Also admits scalar multiplication.
"""
if isinstance(other, (int, float)):
return np.multiply(self, other).view(self.__class__)
else:
check_type_equivalence(other, self)
return self.dot(other)

def __mod__(self, other: "Vector3D") -> "Vector3D":
"""Overload % operator with cross product."""
check_type_equivalence(other, self)
return self.cross(other)
return self.cross(other).view(self.__class__)


class Vector2D(np.ndarray):
Expand Down Expand Up @@ -168,10 +176,18 @@ def __ne__(self, other: "Vector2D") -> bool:
"""Not equals operator for ``Vector2D``."""
return not self == other

def __mul__(self, other: "Vector2D") -> Real:
"""Overload * operator with dot product."""
check_type_equivalence(other, self)
return self.dot(other)
def __mul__(self, other: Union["Vector2D", Real]) -> Union["Vector2D", Real]:
"""Overload * operator with dot product.
Note
----
Also admits scalar multiplication.
"""
if isinstance(other, (int, float)):
return np.multiply(self, other).view(self.__class__)
else:
check_type_equivalence(other, self)
return self.dot(other)


class UnitVector3D(Vector3D):
Expand Down Expand Up @@ -296,6 +312,11 @@ def unit(self, unit: Unit) -> None:
check_pint_unit_compatibility(unit, self._base_unit)
self._unit = unit

@property
def base_unit(self) -> Unit:
"""Returns the base unit of the ``QuantityVector3D``."""
return self._base_unit

def normalize(self) -> "QuantityVector3D":
"""Return a normalized version of the ``QuantityVector3D``"""
vec = Vector3D.normalize(self).view(QuantityVector3D)
Expand Down Expand Up @@ -388,6 +409,11 @@ def unit(self) -> Unit:
"""Returns the unit of the ``QuantityVector2D``."""
return self._unit

@property
def base_unit(self) -> Unit:
"""Returns the base unit of the ``QuantityVector2D``."""
return self._base_unit

@unit.setter
def unit(self, unit: Unit) -> None:
"""Sets the unit of the ``QuantityVector2D``."""
Expand Down
14 changes: 13 additions & 1 deletion src/ansys/geometry/core/misc/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,27 @@
from ansys.geometry.core.misc.checks import (
check_is_float_int,
check_is_pint_unit,
check_is_point,
check_is_quantityvector,
check_is_unitvector,
check_is_vector,
check_ndarray_is_float_int,
check_ndarray_is_non_zero,
check_ndarray_is_not_none,
check_pint_unit_compatibility,
check_type_equivalence,
)

__all__ = [
"check_is_float_int",
"check_is_pint_unit",
"check_is_point",
"check_is_quantityvector",
"check_is_unitvector",
"check_is_vector",
"check_ndarray_is_float_int",
"check_ndarray_is_not_none",
"check_ndarray_is_non_zero",
"check_pint_unit_compatibility",
"check_type_equivalence",
"check_ndarray_is_float_int",
]
182 changes: 182 additions & 0 deletions src/ansys/geometry/core/misc/checks.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,134 @@ def check_is_float_int(param: object, param_name: Optional[Union[str, None]] = N
)


def check_is_point(
param: object, param_name: Optional[Union[str, None]] = None, only_3d: bool = False
) -> None:
"""
Checks if the parameter provided is a ``Point3D`` or ``Point2D``.
Parameters
----------
param : object
Object instance to be checked.
param_name : str or None, optional
The object instance name (if any). By default, ``None``.
only_3d : bool
Only consider ``Point3D`` for checking.
Raises
------
TypeError
In case the parameter is not a ``Point3D`` or a ``Point2D``.
"""
from ansys.geometry.core.math.point import Point2D, Point3D

consider = (Point3D) if only_3d else (Point2D, Point3D)
point_type = "Point3D" if only_3d else "Point3D or Point2D"
if not isinstance(param, consider):
raise TypeError(
f"The parameter provided should be a {point_type} object."
if param_name is None
else f"The parameter '{param_name}' should be a {point_type} object."
)


def check_is_vector(
param: object, param_name: Optional[Union[str, None]] = None, only_3d: bool = False
) -> None:
"""
Checks if the parameter provided is a ``Vector3D`` or ``Vector2D``.
Parameters
----------
param : object
Object instance to be checked.
param_name : str or None, optional
The object instance name (if any). By default, ``None``.
only_3d : bool
Only consider ``Vector3D`` for checking.
Raises
------
TypeError
In case the parameter is not a ``Vector3D`` or a ``Vector2D``.
"""
from ansys.geometry.core.math.vector import Vector2D, Vector3D

consider = (Vector3D) if only_3d else (Vector2D, Vector3D)
vector_type = "Vector3D" if only_3d else "Vector3D or Vector2D"
if not isinstance(param, consider):
raise TypeError(
f"The parameter provided should be a {vector_type} object."
if param_name is None
else f"The parameter '{param_name}' should be a {vector_type} object."
)


def check_is_unitvector(
param: object, param_name: Optional[Union[str, None]] = None, only_3d: bool = False
) -> None:
"""
Checks if the parameter provided is a ``UnitVector3D`` or ``UnitVector2D``.
Parameters
----------
param : object
Object instance to be checked.
param_name : str or None, optional
The object instance name (if any). By default, ``None``.
only_3d : bool
Only consider ``UnitVector3D`` for checking.
Raises
------
TypeError
In case the parameter is not a ``UnitVector3D`` or a ``UnitVector2D``.
"""
from ansys.geometry.core.math.vector import UnitVector2D, UnitVector3D

consider = (UnitVector3D) if only_3d else (UnitVector2D, UnitVector3D)
unit_vector_type = "UnitVector3D" if only_3d else "UnitVector3D or UnitVector2D"
if not isinstance(param, consider):
raise TypeError(
f"The parameter provided should be a {unit_vector_type} object."
if param_name is None
else f"The parameter '{param_name}' should be a {unit_vector_type} object."
)


def check_is_quantityvector(
param: object, param_name: Optional[Union[str, None]] = None, only_3d: bool = False
) -> None:
"""
Checks if the parameter provided is a ``QuantityVector3D`` or ``QuantityVector2D``.
Parameters
----------
param : object
Object instance to be checked.
param_name : str or None, optional
The object instance name (if any). By default, ``None``.
only_3d : bool
Only consider ``QuantityVector3D`` for checking.
Raises
------
TypeError
In case the parameter is not a ``QuantityVector3D`` or a ``QuantityVector2D``.
"""
from ansys.geometry.core.math.vector import QuantityVector2D, QuantityVector3D

consider = (QuantityVector3D) if only_3d else (QuantityVector2D, QuantityVector3D)
quantity_vector_type = "QuantityVector3D" if only_3d else "QuantityVector3D or QuantityVector2D"
if not isinstance(param, consider):
raise TypeError(
f"The parameter provided should be a {quantity_vector_type} object."
if param_name is None
else f"The parameter '{param_name}' should be a {quantity_vector_type} object."
)


def check_ndarray_is_float_int(
param: np.ndarray, param_name: Optional[Union[str, None]] = None
) -> None:
Expand Down Expand Up @@ -60,6 +188,60 @@ def check_ndarray_is_float_int(
)


def check_ndarray_is_not_none(
param: np.ndarray, param_name: Optional[Union[str, None]] = None
) -> None:
"""
Checks if the :class:`numpy.ndarray` is not None-valued.
Parameters
----------
param : ~numpy.ndarray
:class:`numpy.ndarray` instance to be checked.
param_name : str or None, optional
The :class:`numpy.ndarray` instance name (if any). By default, ``None``.
Raises
------
ValueError
In case the :class:`numpy.ndarray` is None-valued.
"""
param_data = np.ravel(param)
if all(value is None for value in param_data):
raise ValueError(
f"The numpy.ndarray provided should not be a None numpy.ndarray."
if param_name is None
else f"The numpy.ndarray '{param_name}' should not be a None numpy.ndarray."
)


def check_ndarray_is_non_zero(
param: np.ndarray, param_name: Optional[Union[str, None]] = None
) -> None:
"""
Checks if the :class:`numpy.ndarray` is not zero-valued.
Parameters
----------
param : ~numpy.ndarray
:class:`numpy.ndarray` instance to be checked.
param_name : str or None, optional
The :class:`numpy.ndarray` instance name (if any). By default, ``None``.
Raises
------
ValueError
In case the :class:`numpy.ndarray` is zero-valued.
"""
param_data = np.ravel(param)
if all(value == 0 for value in param_data):
raise ValueError(
f"The numpy.ndarray provided should not be a numpy.ndarray of zeros."
if param_name is None
else f"The numpy.ndarray '{param_name}' should not be a numpy.ndarray of zeros."
)


def check_is_pint_unit(param: object, param_name: Optional[Union[str, None]] = None) -> None:
"""
Checks if the parameter provided is a :class:`pint.Unit`.
Expand Down
8 changes: 4 additions & 4 deletions src/ansys/geometry/core/shapes/__init__.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
"""PyGeometry shapes subpackage."""

from ansys.geometry.core.shapes.base import BaseShape
from ansys.geometry.core.shapes.circle import CircleShape
from ansys.geometry.core.shapes.ellipse import EllipseShape
from ansys.geometry.core.shapes.line import LineShape
from ansys.geometry.core.shapes.circle import Circle
from ansys.geometry.core.shapes.ellipse import Ellipse
from ansys.geometry.core.shapes.line import Line, Segment

__all__ = ["BaseShape", "CircleShape", "EllipseShape", "LineShape"]
__all__ = ["BaseShape", "Circle", "Ellipse", "Line", "Segment"]
Loading

0 comments on commit da5dffd

Please sign in to comment.