Skip to content

Commit

Permalink
Merge pull request #1328 from compas-dev/fix-quaternion
Browse files Browse the repository at this point in the history
Fixed a few bugs in `Quaternion`
  • Loading branch information
gonzalocasas committed Apr 22, 2024
2 parents a584b06 + 4cd17b5 commit 9c1216c
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 13 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* Changed to implementation of `Mesh.unify_cycles` to use the corresponding function of `compas.topology.orientation`.
* Fixed bug in `compas.topology.orientation.unify_cycles`.
* Fixed bug in `Mesh.thickened`.
* Fixed various bugs in `compas.geometry.Quaternion`.


### Removed

Expand Down
18 changes: 10 additions & 8 deletions src/compas/geometry/quaternion.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ def __getitem__(self, key):
return self.y
if key == 3:
return self.z
raise KeyError
raise KeyError(key)

def __setitem__(self, key, value):
if key == 0:
Expand All @@ -170,9 +170,11 @@ def __setitem__(self, key, value):
return
if key == 2:
self.y = value
return
if key == 3:
self.z = value
raise KeyError
return
raise KeyError(key)

def __iter__(self):
return iter(self.wxyz)
Expand Down Expand Up @@ -367,7 +369,7 @@ def unitize(self):
True
"""
qu = quaternion_unitize(self)
qu = quaternion_unitize(list(self))
self.w, self.x, self.y, self.z = qu

def unitized(self):
Expand All @@ -387,7 +389,7 @@ def unitized(self):
True
"""
qu = quaternion_unitize(self)
qu = quaternion_unitize(list(self))
return Quaternion(*qu)

def canonize(self):
Expand All @@ -408,7 +410,7 @@ def canonize(self):
Quaternion(0.500, -0.500, -0.500, -0.500)
"""
qc = quaternion_canonize(self)
qc = quaternion_canonize(list(self))
self.w, self.x, self.y, self.z = qc # type: ignore

def canonized(self):
Expand All @@ -430,7 +432,7 @@ def canonized(self):
Quaternion(0.500, -0.500, -0.500, -0.500)
"""
qc = quaternion_canonize(self)
qc = quaternion_canonize(list(self))
return Quaternion(*qc) # type: ignore

def conjugate(self):
Expand All @@ -448,7 +450,7 @@ def conjugate(self):
Quaternion(1.000, -1.000, -1.000, -1.000)
"""
qc = quaternion_conjugate(self)
qc = quaternion_conjugate(list(self))
self.w, self.x, self.y, self.z = qc

def conjugated(self):
Expand All @@ -469,5 +471,5 @@ def conjugated(self):
Quaternion(1.000, -1.000, -1.000, -1.000)
"""
qc = quaternion_conjugate(self)
qc = quaternion_conjugate(list(self))
return Quaternion(*qc)
78 changes: 73 additions & 5 deletions tests/compas/geometry/test_quaternion.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

from compas.geometry import Quaternion
from compas.geometry import close
from compas.geometry import Frame


@pytest.mark.parametrize(
Expand Down Expand Up @@ -63,22 +64,89 @@ def test_quaternion_data():
assert Quaternion.validate_data(other.__data__)


# =============================================================================
# Constructors
# =============================================================================

# =============================================================================
# Properties and Geometry
# =============================================================================


def test_quaternion_properties():
w = 1.0
x = 2.0
y = 3.0
z = 4.0

quaternion = Quaternion(w, x, y, z)

assert quaternion.wxyz == [w, x, y, z]
assert quaternion.xyzw == [x, y, z, w]
assert close(quaternion.norm, 5.4772255)
assert quaternion.is_unit is False

quaternion = Quaternion(0.0, 0.0, 0.0, 1.0)
assert quaternion.norm == 1.0


# =============================================================================
# Accessors
# =============================================================================


def test_quaternion_accessors():
w = 1.0
x = 2.0
y = 3.0
z = 4.0

quaternion = Quaternion(w, x, y, z)

assert quaternion[0] == w
assert quaternion[1] == x
assert quaternion[2] == y
assert quaternion[3] == z

quaternion[0] = 5.0
quaternion[1] = 6.0
quaternion[2] = 7.0
quaternion[3] = 8.0

assert quaternion.w == 5.0
assert quaternion.x == 6.0
assert quaternion.y == 7.0
assert quaternion.z == 8.0


# =============================================================================
# Comparison
# =============================================================================


def test_quaternion_comparison():
quaternion1 = Quaternion(1.0, 2.0, 3.0, 4.0)
quaternion2 = Quaternion(1.0, 2.0, 3.0, 4.0)
quaternion3 = Quaternion(5.0, 6.0, 7.0, 8.0)

assert quaternion1 == quaternion2
assert quaternion1 != quaternion3


# =============================================================================
# Other Methods
# Methods
# =============================================================================


def test_quaternion_other_methods():
quaternion = Quaternion(1.0, 2.0, 3.0, 4.0)

conjugate = quaternion.conjugated()
assert conjugate.w == 1.0
assert conjugate.x == -2.0
assert conjugate.y == -3.0
assert conjugate.z == -4.0

unitized = quaternion.unitized()
assert unitized.is_unit

quaternion = Quaternion.from_frame(Frame.worldZX())
canonized = quaternion.canonized()

assert str(canonized) == str("Quaternion(0.5, -0.5, -0.5, -0.5)")

0 comments on commit 9c1216c

Please sign in to comment.