@@ -26,7 +26,7 @@ def vec_normalize(vectors, /, *, out=None, dtype=None) -> np.ndarray:
26
26
ndarray, [..., 3]
27
27
array of normalized vectors.
28
28
"""
29
- vectors = np .asarray (vectors , dtype = np . float64 )
29
+ vectors = np .asarray (vectors , dtype = float )
30
30
if out is None :
31
31
out = np .empty_like (vectors , dtype = dtype )
32
32
@@ -102,14 +102,15 @@ def vec_transform(vectors, matrix, /, *, w=1, out=None, dtype=None) -> np.ndarra
102
102
vectors = np .asarray (vectors , dtype = float )
103
103
matrix = np .asarray (matrix , dtype = float )
104
104
105
- if out is None :
106
- out_shape = np .broadcast_shapes (vectors .shape [:- 1 ], matrix .shape [:- 2 ])
107
- out = np .empty ((* out_shape , 3 ), dtype = dtype )
108
-
109
105
vectors = vec_homogeneous (vectors , w = w )
110
106
result = matrix @ vectors [..., None ]
111
107
result /= result [..., - 1 , :][..., None , :]
112
- out [:] = result [..., :- 1 , 0 ]
108
+ result = result [..., :- 1 , 0 ]
109
+
110
+ if out is not None :
111
+ out [:] = result
112
+ else :
113
+ out = result .astype (dtype , copy = False )
113
114
114
115
return out
115
116
@@ -482,7 +483,9 @@ def vec_spherical_safe(vector, /, *, out=None, dtype=None) -> np.ndarray:
482
483
return out
483
484
484
485
485
- def quat_to_euler (quaternion , / , * , order = "xyz" , out = None , dtype = None ) -> np .ndarray :
486
+ def quat_to_euler (
487
+ quaternion , / , * , order = "xyz" , epsilon = 1e-7 , out = None , dtype = None
488
+ ) -> np .ndarray :
486
489
"""Convert quaternions to Euler angles with specified rotation order.
487
490
488
491
Parameters
@@ -493,6 +496,8 @@ def quat_to_euler(quaternion, /, *, order="xyz", out=None, dtype=None) -> np.nda
493
496
The rotation order as a string. Can include 'X', 'Y', 'Z' for intrinsic
494
497
rotation (uppercase) or 'x', 'y', 'z' for extrinsic rotation (lowercase).
495
498
Default is "xyz".
499
+ epsilon : float, optional
500
+ The floating point error margin. Default is 1e-7.
496
501
out : ndarray, optional
497
502
A location into which the result is stored. If provided, it
498
503
must have a shape that the inputs broadcast to. If not provided or
@@ -538,7 +543,6 @@ def quat_to_euler(quaternion, /, *, order="xyz", out=None, dtype=None) -> np.nda
538
543
# Check if permutation is even (+1) or odd (-1)
539
544
sign = int ((i - j ) * (j - k ) * (k - i ) / 2 )
540
545
541
- eps = 1e-7
542
546
for ind in range (num_rotations ):
543
547
if num_rotations == 1 and out .ndim == 1 :
544
548
_angles = out
@@ -564,8 +568,8 @@ def quat_to_euler(quaternion, /, *, order="xyz", out=None, dtype=None) -> np.nda
564
568
_angles [1 ] = np .arccos (2 * (a ** 2 + b ** 2 ) / n2 - 1 )
565
569
566
570
# ... and check if it is equal to 0 or pi, causing a singularity
567
- safe1 = np .abs (_angles [1 ]) >= eps
568
- safe2 = np .abs (_angles [1 ] - np .pi ) >= eps
571
+ safe1 = np .abs (_angles [1 ]) >= epsilon
572
+ safe2 = np .abs (_angles [1 ] - np .pi ) >= epsilon
569
573
safe = safe1 and safe2
570
574
571
575
# Step 4
0 commit comments