Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: matrix operations #1649

Open
wants to merge 8 commits into
base: blitz
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions doc/changelog.d/1649.added.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
matrix operations
44 changes: 43 additions & 1 deletion src/ansys/geometry/core/math/matrix.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,12 @@
# SOFTWARE.
"""Provides matrix primitive representations."""

from typing import Union
from typing import TYPE_CHECKING, Union

if TYPE_CHECKING:
from ansys.geometry.core.math.frame import Frame # For type hints
from ansys.geometry.core.math.point import Point3D # For type hints
from ansys.geometry.core.math.vector import Vector3D # For type hints

from beartype import beartype as check_input_types
import numpy as np
Expand Down Expand Up @@ -129,3 +134,40 @@ def __new__(cls, input: np.ndarray | RealSequence | Matrix = DEFAULT_MATRIX44):
raise ValueError("Matrix44 should only be a 2D array of shape (4,4).")

return obj

@classmethod
def create_matrix_from_rotation(
cls, direction_x: "Vector3D", direction_y: "Vector3D"
) -> "Matrix44":
"""Matrix44 helper method -- create_matrix_from_rotation."""
matrix = cls(
[
[direction_x.x, direction_x.y, direction_x.z, 0],
[direction_y.x, direction_y.y, direction_y.z, 0],
[0, 0, 1, 0],
[0, 0, 0, 1],
]
)
return matrix

@classmethod
def create_matrix_from_translation(cls, origin: "Point3D") -> "Matrix44":
"""Matrix44 helper method -- create_matrix_from_translation."""
print(origin)
matrix = cls(
[
[1, 0, 0, origin.x.m],
[0, 1, 0, origin.y.m],
[0, 0, 1, origin.z.m],
[0, 0, 0, 1],
]
)
return matrix

@classmethod
def create_matrix_from_mapping(cls, frame: "Frame") -> "Matrix44": # noqa
"""Matrix44 helper method -- create_matrix_from_mapping."""
translation_matrix = cls.create_matrix_from_translation(frame.origin)
rotation_matrix = cls.create_matrix_from_rotation(frame.direction_x, frame.direction_y)

return translation_matrix * rotation_matrix
16 changes: 16 additions & 0 deletions src/ansys/geometry/core/math/vector.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import numpy as np
from pint import Quantity

from ansys.geometry.core import math
from ansys.geometry.core.math.matrix import Matrix44
from ansys.geometry.core.math.point import Point2D, Point3D
from ansys.geometry.core.misc.accuracy import Accuracy
Expand Down Expand Up @@ -265,6 +266,21 @@ class representing the second point.
"""
return Vector3D(point_b - point_a)

@staticmethod
def rotate_vector(_this: "Vector3D", vector: "Vector3D", angle: float) -> "Vector3D":
"""Vector3D helper method -- rotate_vector."""
if _this.is_zero:
raise Exception("Invalid vector operation.")

angle_between = vector.get_angle_between(_this)
parallel = Vector3D(
vector.x * angle_between, vector.y * angle_between, vector.z * angle_between
)

perpendicular1 = vector - parallel
perpendicular2 = _this.cross(perpendicular1)
return parallel + perpendicular1 * math.cos(angle) + perpendicular2 * math.sin(angle)


class Vector2D(np.ndarray):
"""Provides for creating and managing a 2D vector.
Expand Down
29 changes: 29 additions & 0 deletions tests/test_math.py
Original file line number Diff line number Diff line change
Expand Up @@ -752,6 +752,35 @@ def test_matrix_44():
assert "Matrix44 should only be a 2D array of shape (4,4)." in str(val.value)


def test_create_matrix_from_rotation():
direction_x = Vector3D([1, 0, 0])
direction_y = Vector3D([0, 1, 0])

expected_matrix = Matrix44([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]])
rotation_matrix = Matrix44.create_matrix_from_rotation(direction_x, direction_y)
assert np.array_equal(expected_matrix, rotation_matrix)


def test_create_matrix_from_translation():
origin = Vector3D([1, 2, 3])

expected_matrix = Matrix44([[1, 0, 0, 1], [0, 1, 0, 2], [0, 0, 1, 3], [0, 0, 0, 1]])
translation_matrix = Matrix44.create_matrix_from_translation(origin)
umutsoysalansys marked this conversation as resolved.
Show resolved Hide resolved
assert np.array_equal(expected_matrix, translation_matrix)


def test_create_matrix_from_mapping():
origin = Vector3D([1, 2, 3])
direction_x = Vector3D([1, 0, 0])
direction_y = Vector3D([0, 1, 0])
frame = Frame(origin, direction_x, direction_y)

expected_matrix = Matrix44([[1, 0, 0, 1], [0, 1, 0, 2], [0, 0, 1, 3], [0, 0, 0, 1]])

mapping_matrix = Matrix44.create_matrix_from_mapping(frame)
assert np.array_equal(expected_matrix, mapping_matrix)


def test_frame():
"""``Frame`` construction and equivalency."""
origin = Point3D([42, 99, 13])
Expand Down
Loading