@sachitv/safe-math-ts 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,6 @@
1
+ export { frame } from './types.js';
2
+ export type { Delta3, Dir3, FrameTag, LinearMat4, Mat4, Point3, ProjectionMat4, Quaternion, } from './types.js';
3
+ export { addPoint3, addVec3, angleBetweenVec3, angleBetweenVec3Unsafe, crossVec3, delta3, dir3, distancePoint3, distanceVec3, dotVec3, lengthSquaredVec3, lengthVec3, lerpVec3, negVec3, normalizeVec3, normalizeVec3Unsafe, point3, projectVec3, projectVec3Unsafe, reflectVec3, reflectVec3Unsafe, scaleDir3, scaleVec3, subPoint3, subPoint3Delta3, subVec3, zeroVec3, } from './vector3.js';
4
+ export { composeQuats, type EulerOrder, quat, quatConjugate, quatFromAxisAngle, quatFromAxisAngleUnsafe, quatFromEuler, quatFromEulerUnsafe, quatIdentity, quatInverse, quatInverseUnsafe, quatNlerp, quatNlerpUnsafe, quatNorm, quatNormalize, quatNormalizeUnsafe, quatNormSquared, quatSlerp, quatSlerpUnsafe, rotateVec3ByQuat, rotateVec3ByQuatUnsafe, } from './quaternion.js';
5
+ export { composeMat4, createTrsMat4Cache, invertRigidMat4, invertRigidMat4Unsafe, mat4, mat4FromQuaternion, mat4FromQuaternionUnsafe, mat4FromRigidTransform, mat4FromScale, mat4FromTranslation, mat4FromTRS, mat4FromTRSUnsafe, mat4Identity, mat4LookAt, mat4LookAtUnsafe, mat4Ortho, mat4OrthoUnsafe, mat4Perspective, mat4PerspectiveUnsafe, mat4Unsafe, normalMatrixFromMat4, normalMatrixFromMat4Unsafe, projectPoint3, projectPoint3Unsafe, transformDirection3, transformPoint3, transposeMat4, } from './matrix4.js';
6
+ //# sourceMappingURL=mod.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["../../../src/src/geometry3d/mod.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,YAAY,EACV,MAAM,EACN,IAAI,EACJ,QAAQ,EACR,UAAU,EACV,IAAI,EACJ,MAAM,EACN,cAAc,EACd,UAAU,GACX,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,SAAS,EACT,OAAO,EACP,gBAAgB,EAChB,sBAAsB,EACtB,SAAS,EACT,MAAM,EACN,IAAI,EACJ,cAAc,EACd,YAAY,EACZ,OAAO,EACP,iBAAiB,EACjB,UAAU,EACV,QAAQ,EACR,OAAO,EACP,aAAa,EACb,mBAAmB,EACnB,MAAM,EACN,WAAW,EACX,iBAAiB,EACjB,WAAW,EACX,iBAAiB,EACjB,SAAS,EACT,SAAS,EACT,SAAS,EACT,eAAe,EACf,OAAO,EACP,QAAQ,GACT,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,YAAY,EACZ,KAAK,UAAU,EACf,IAAI,EACJ,aAAa,EACb,iBAAiB,EACjB,uBAAuB,EACvB,aAAa,EACb,mBAAmB,EACnB,YAAY,EACZ,WAAW,EACX,iBAAiB,EACjB,SAAS,EACT,eAAe,EACf,QAAQ,EACR,aAAa,EACb,mBAAmB,EACnB,eAAe,EACf,SAAS,EACT,eAAe,EACf,gBAAgB,EAChB,sBAAsB,GACvB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EACL,WAAW,EACX,kBAAkB,EAClB,eAAe,EACf,qBAAqB,EACrB,IAAI,EACJ,kBAAkB,EAClB,wBAAwB,EACxB,sBAAsB,EACtB,aAAa,EACb,mBAAmB,EACnB,WAAW,EACX,iBAAiB,EACjB,YAAY,EACZ,UAAU,EACV,gBAAgB,EAChB,SAAS,EACT,eAAe,EACf,eAAe,EACf,qBAAqB,EACrB,UAAU,EACV,oBAAoB,EACpB,0BAA0B,EAC1B,aAAa,EACb,mBAAmB,EACnB,mBAAmB,EACnB,eAAe,EACf,aAAa,GACd,MAAM,cAAc,CAAC"}
@@ -0,0 +1,4 @@
1
+ export { frame } from './types.js';
2
+ export { addPoint3, addVec3, angleBetweenVec3, angleBetweenVec3Unsafe, crossVec3, delta3, dir3, distancePoint3, distanceVec3, dotVec3, lengthSquaredVec3, lengthVec3, lerpVec3, negVec3, normalizeVec3, normalizeVec3Unsafe, point3, projectVec3, projectVec3Unsafe, reflectVec3, reflectVec3Unsafe, scaleDir3, scaleVec3, subPoint3, subPoint3Delta3, subVec3, zeroVec3, } from './vector3.js';
3
+ export { composeQuats, quat, quatConjugate, quatFromAxisAngle, quatFromAxisAngleUnsafe, quatFromEuler, quatFromEulerUnsafe, quatIdentity, quatInverse, quatInverseUnsafe, quatNlerp, quatNlerpUnsafe, quatNorm, quatNormalize, quatNormalizeUnsafe, quatNormSquared, quatSlerp, quatSlerpUnsafe, rotateVec3ByQuat, rotateVec3ByQuatUnsafe, } from './quaternion.js';
4
+ export { composeMat4, createTrsMat4Cache, invertRigidMat4, invertRigidMat4Unsafe, mat4, mat4FromQuaternion, mat4FromQuaternionUnsafe, mat4FromRigidTransform, mat4FromScale, mat4FromTranslation, mat4FromTRS, mat4FromTRSUnsafe, mat4Identity, mat4LookAt, mat4LookAtUnsafe, mat4Ortho, mat4OrthoUnsafe, mat4Perspective, mat4PerspectiveUnsafe, mat4Unsafe, normalMatrixFromMat4, normalMatrixFromMat4Unsafe, projectPoint3, projectPoint3Unsafe, transformDirection3, transformPoint3, transposeMat4, } from './matrix4.js';
@@ -0,0 +1,221 @@
1
+ import { type NoInfer, type UnitExpr } from '../units.js';
2
+ import type { Delta3, Dir3, FrameTag, Quaternion } from './types.js';
3
+ /** Axis composition order for Euler rotations. */
4
+ export type EulerOrder = 'XYZ' | 'XZY' | 'YXZ' | 'YZX' | 'ZXY' | 'ZYX';
5
+ /**
6
+ * Constructs a frame-aware quaternion.
7
+ *
8
+ * `toFrameTag` and `fromFrameTag` are required to enforce explicit frame declaration.
9
+ *
10
+ * @param toFrameTag Destination frame token.
11
+ * @param fromFrameTag Source frame token.
12
+ * @param x Quaternion x component.
13
+ * @param y Quaternion y component.
14
+ * @param z Quaternion z component.
15
+ * @param w Quaternion w component.
16
+ * @returns Quaternion in `<ToFrame, FromFrame>` order.
17
+ */
18
+ export declare const quat: <ToFrame extends string, FromFrame extends string>(toFrameTag: FrameTag<ToFrame>, fromFrameTag: FrameTag<FromFrame>, x: number, y: number, z: number, w: number) => Quaternion<ToFrame, FromFrame>;
19
+ /**
20
+ * Returns identity quaternion for a frame.
21
+ *
22
+ * @param frameTag Frame token.
23
+ * @returns Identity rotation for the frame.
24
+ */
25
+ export declare const quatIdentity: <Frame extends string>(frameTag: FrameTag<Frame>) => Quaternion<Frame, Frame>;
26
+ /**
27
+ * Computes quaternion conjugate.
28
+ *
29
+ * @param value Input quaternion.
30
+ * @returns Conjugated quaternion with swapped frame direction.
31
+ */
32
+ export declare const quatConjugate: <ToFrame extends string, FromFrame extends string>(value: Quaternion<ToFrame, FromFrame>) => Quaternion<FromFrame, ToFrame>;
33
+ /**
34
+ * Computes squared quaternion norm.
35
+ *
36
+ * @param value Input quaternion.
37
+ * @returns Squared norm.
38
+ */
39
+ export declare const quatNormSquared: <ToFrame extends string, FromFrame extends string>(value: Quaternion<ToFrame, FromFrame>) => number;
40
+ /**
41
+ * Computes quaternion norm.
42
+ *
43
+ * @param value Input quaternion.
44
+ * @returns Euclidean norm.
45
+ */
46
+ export declare const quatNorm: <ToFrame extends string, FromFrame extends string>(value: Quaternion<ToFrame, FromFrame>) => number;
47
+ /**
48
+ * Normalizes quaternion length to 1.
49
+ *
50
+ * Unsafe variant: performs no zero-length guard.
51
+ * Degenerate inputs can yield `NaN`/`Infinity`.
52
+ *
53
+ * @param value Quaternion to normalize.
54
+ * @returns Unit quaternion.
55
+ */
56
+ export declare const quatNormalizeUnsafe: <ToFrame extends string, FromFrame extends string>(value: Quaternion<ToFrame, FromFrame>) => Quaternion<ToFrame, FromFrame>;
57
+ /**
58
+ * Normalizes quaternion length to 1.
59
+ *
60
+ * Throws when quaternion norm is zero.
61
+ *
62
+ * @param value Quaternion to normalize.
63
+ * @returns Unit quaternion.
64
+ * @throws {Error} When the quaternion is near zero length.
65
+ */
66
+ export declare const quatNormalize: <ToFrame extends string, FromFrame extends string>(value: Quaternion<ToFrame, FromFrame>) => Quaternion<ToFrame, FromFrame>;
67
+ /**
68
+ * Computes quaternion inverse.
69
+ *
70
+ * Unsafe variant: performs no zero-length guard.
71
+ * Degenerate inputs can yield `NaN`/`Infinity`.
72
+ *
73
+ * @param value Quaternion to invert.
74
+ * @returns Inverse quaternion in swapped frame direction.
75
+ */
76
+ export declare const quatInverseUnsafe: <ToFrame extends string, FromFrame extends string>(value: Quaternion<ToFrame, FromFrame>) => Quaternion<FromFrame, ToFrame>;
77
+ /**
78
+ * Computes quaternion inverse.
79
+ *
80
+ * Throws when quaternion norm is zero.
81
+ *
82
+ * @param value Quaternion to invert.
83
+ * @returns Inverse quaternion in swapped frame direction.
84
+ * @throws {Error} When the quaternion is near zero length.
85
+ */
86
+ export declare const quatInverse: <ToFrame extends string, FromFrame extends string>(value: Quaternion<ToFrame, FromFrame>) => Quaternion<FromFrame, ToFrame>;
87
+ /**
88
+ * Composes two frame-compatible quaternions in chain order.
89
+ *
90
+ * `composeQuats(outer, inner)` returns `outer * inner`, so `inner` is applied
91
+ * first.
92
+ *
93
+ * @param outer Outer rotation.
94
+ * @param inner Inner rotation.
95
+ * @returns Composed rotation `outer * inner`.
96
+ */
97
+ export declare const composeQuats: <ToFrame extends string, ViaFrame extends string, FromFrame extends string>(outer: Quaternion<ToFrame, ViaFrame>, inner: Quaternion<NoInfer<ViaFrame>, FromFrame>) => Quaternion<ToFrame, FromFrame>;
98
+ /**
99
+ * Rotates a displacement vector from `FromFrame` into `ToFrame`.
100
+ *
101
+ * @param rotation Quaternion mapping `FromFrame -> ToFrame`.
102
+ * @param value Displacement to rotate.
103
+ * @returns Rotated displacement in `ToFrame`.
104
+ */
105
+ export declare function rotateVec3ByQuatUnsafe<Unit extends UnitExpr, ToFrame extends string, FromFrame extends string>(rotation: Quaternion<ToFrame, FromFrame>, value: Delta3<Unit, NoInfer<FromFrame>>): Delta3<Unit, ToFrame>;
106
+ /**
107
+ * Rotates a direction vector from `FromFrame` into `ToFrame`.
108
+ *
109
+ * @param rotation Quaternion mapping `FromFrame -> ToFrame`.
110
+ * @param value Direction to rotate.
111
+ * @returns Rotated direction in `ToFrame`.
112
+ */
113
+ export declare function rotateVec3ByQuatUnsafe<ToFrame extends string, FromFrame extends string>(rotation: Quaternion<ToFrame, FromFrame>, value: Dir3<NoInfer<FromFrame>>): Dir3<ToFrame>;
114
+ /**
115
+ * Rotates a displacement vector from `FromFrame` into `ToFrame`.
116
+ *
117
+ * @param rotation Quaternion mapping `FromFrame -> ToFrame`.
118
+ * @param value Displacement to rotate.
119
+ * @returns Rotated displacement in `ToFrame`.
120
+ */
121
+ export declare function rotateVec3ByQuat<Unit extends UnitExpr, ToFrame extends string, FromFrame extends string>(rotation: Quaternion<ToFrame, FromFrame>, value: Delta3<Unit, NoInfer<FromFrame>>): Delta3<Unit, ToFrame>;
122
+ /**
123
+ * Rotates a direction vector from `FromFrame` into `ToFrame`.
124
+ *
125
+ * @param rotation Quaternion mapping `FromFrame -> ToFrame`.
126
+ * @param value Direction to rotate.
127
+ * @returns Rotated direction in `ToFrame`.
128
+ */
129
+ export declare function rotateVec3ByQuat<ToFrame extends string, FromFrame extends string>(rotation: Quaternion<ToFrame, FromFrame>, value: Dir3<NoInfer<FromFrame>>): Dir3<ToFrame>;
130
+ /**
131
+ * Creates a quaternion from axis-angle representation.
132
+ *
133
+ * Axis is normalized internally.
134
+ * Unsafe variant: performs no zero-length guard for `axis`.
135
+ *
136
+ * @param frameTag Frame token.
137
+ * @param axis Rotation axis.
138
+ * @param angleRadians Rotation angle in radians.
139
+ * @returns Quaternion in `<Frame, Frame>` order.
140
+ */
141
+ export declare const quatFromAxisAngleUnsafe: <Frame extends string>(frameTag: FrameTag<Frame>, axis: Dir3<Frame>, angleRadians: number) => Quaternion<Frame, Frame>;
142
+ /**
143
+ * Creates a quaternion from axis-angle representation.
144
+ *
145
+ * Axis is normalized internally.
146
+ * Throws when axis has zero length.
147
+ *
148
+ * @param frameTag Frame token.
149
+ * @param axis Rotation axis.
150
+ * @param angleRadians Rotation angle in radians.
151
+ * @returns Quaternion in `<Frame, Frame>` order.
152
+ * @throws {Error} When `axis` is near zero length.
153
+ */
154
+ export declare const quatFromAxisAngle: <Frame extends string>(frameTag: FrameTag<Frame>, axis: Dir3<Frame>, angleRadians: number) => Quaternion<Frame, Frame>;
155
+ /**
156
+ * Builds a frame-local quaternion from Euler angles and explicit axis order.
157
+ *
158
+ * Rotations are composed in intrinsic order: the `order` string describes
159
+ * which axis is applied first (leftmost) through last (rightmost). For example
160
+ * `'ZYX'` applies Z first, then Y, then X.
161
+ *
162
+ * @param frameTag Frame token.
163
+ * @param xRadians Rotation around X axis in radians.
164
+ * @param yRadians Rotation around Y axis in radians.
165
+ * @param zRadians Rotation around Z axis in radians.
166
+ * @param order Euler axis composition order.
167
+ * @returns Quaternion in `<Frame, Frame>` order.
168
+ */
169
+ export declare const quatFromEulerUnsafe: <Frame extends string>(frameTag: FrameTag<Frame>, xRadians: number, yRadians: number, zRadians: number, order?: EulerOrder) => Quaternion<Frame, Frame>;
170
+ /**
171
+ * Builds a frame-local quaternion from Euler angles and explicit axis order.
172
+ *
173
+ * Rotations are composed in intrinsic order: the `order` string describes
174
+ * which axis is applied first (leftmost) through last (rightmost). For example
175
+ * `'ZYX'` applies Z first, then Y, then X.
176
+ *
177
+ * @param frameTag Frame token.
178
+ * @param xRadians Rotation around X axis in radians.
179
+ * @param yRadians Rotation around Y axis in radians.
180
+ * @param zRadians Rotation around Z axis in radians.
181
+ * @param order Euler axis composition order.
182
+ * @returns Normalized quaternion in `<Frame, Frame>` order.
183
+ */
184
+ export declare const quatFromEuler: <Frame extends string>(frameTag: FrameTag<Frame>, xRadians: number, yRadians: number, zRadians: number, order?: EulerOrder) => Quaternion<Frame, Frame>;
185
+ /**
186
+ * Normalized linear interpolation with shortest-path hemisphere selection.
187
+ *
188
+ * @param start Start quaternion.
189
+ * @param end End quaternion.
190
+ * @param t Interpolation parameter.
191
+ * @returns Interpolated normalized quaternion.
192
+ */
193
+ export declare const quatNlerpUnsafe: <ToFrame extends string, FromFrame extends string>(start: Quaternion<ToFrame, FromFrame>, end: Quaternion<NoInfer<ToFrame>, NoInfer<FromFrame>>, t: number) => Quaternion<ToFrame, FromFrame>;
194
+ /**
195
+ * Normalized linear interpolation with shortest-path hemisphere selection.
196
+ *
197
+ * @param start Start quaternion.
198
+ * @param end End quaternion.
199
+ * @param t Interpolation parameter.
200
+ * @returns Interpolated normalized quaternion.
201
+ */
202
+ export declare const quatNlerp: <ToFrame extends string, FromFrame extends string>(start: Quaternion<ToFrame, FromFrame>, end: Quaternion<NoInfer<ToFrame>, NoInfer<FromFrame>>, t: number) => Quaternion<ToFrame, FromFrame>;
203
+ /**
204
+ * Spherical interpolation with shortest-path hemisphere selection.
205
+ *
206
+ * @param start Start quaternion.
207
+ * @param end End quaternion.
208
+ * @param t Interpolation parameter.
209
+ * @returns Interpolated normalized quaternion.
210
+ */
211
+ export declare const quatSlerpUnsafe: <ToFrame extends string, FromFrame extends string>(start: Quaternion<ToFrame, FromFrame>, end: Quaternion<NoInfer<ToFrame>, NoInfer<FromFrame>>, t: number) => Quaternion<ToFrame, FromFrame>;
212
+ /**
213
+ * Spherical interpolation with shortest-path hemisphere selection.
214
+ *
215
+ * @param start Start quaternion.
216
+ * @param end End quaternion.
217
+ * @param t Interpolation parameter.
218
+ * @returns Interpolated normalized quaternion.
219
+ */
220
+ export declare const quatSlerp: <ToFrame extends string, FromFrame extends string>(start: Quaternion<ToFrame, FromFrame>, end: Quaternion<NoInfer<ToFrame>, NoInfer<FromFrame>>, t: number) => Quaternion<ToFrame, FromFrame>;
221
+ //# sourceMappingURL=quaternion.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"quaternion.d.ts","sourceRoot":"","sources":["../../../src/src/geometry3d/quaternion.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,419 @@
1
+ import { normalizeVec3, normalizeVec3Unsafe } from './vector3.js';
2
+ const NEAR_ZERO = 1e-14;
3
+ /**
4
+ * Casts a raw number into a branded quantity.
5
+ *
6
+ * @param value Raw numeric scalar.
7
+ * @returns Branded quantity.
8
+ */
9
+ const asQuantity = (value) => value;
10
+ /**
11
+ * Casts xyzw components to a branded quaternion.
12
+ *
13
+ * @param x Quaternion x component.
14
+ * @param y Quaternion y component.
15
+ * @param z Quaternion z component.
16
+ * @param w Quaternion w component.
17
+ * @returns Branded quaternion.
18
+ */
19
+ const asQuaternion = (x, y, z, w) => [x, y, z, w];
20
+ /**
21
+ * Constructs a frame-aware quaternion.
22
+ *
23
+ * `toFrameTag` and `fromFrameTag` are required to enforce explicit frame declaration.
24
+ *
25
+ * @param toFrameTag Destination frame token.
26
+ * @param fromFrameTag Source frame token.
27
+ * @param x Quaternion x component.
28
+ * @param y Quaternion y component.
29
+ * @param z Quaternion z component.
30
+ * @param w Quaternion w component.
31
+ * @returns Quaternion in `<ToFrame, FromFrame>` order.
32
+ */
33
+ export const quat = (toFrameTag, fromFrameTag, x, y, z, w) => {
34
+ void toFrameTag;
35
+ void fromFrameTag;
36
+ return asQuaternion(x, y, z, w);
37
+ };
38
+ /**
39
+ * Returns identity quaternion for a frame.
40
+ *
41
+ * @param frameTag Frame token.
42
+ * @returns Identity rotation for the frame.
43
+ */
44
+ export const quatIdentity = (frameTag) => {
45
+ void frameTag;
46
+ return asQuaternion(0, 0, 0, 1);
47
+ };
48
+ /**
49
+ * Computes quaternion conjugate.
50
+ *
51
+ * @param value Input quaternion.
52
+ * @returns Conjugated quaternion with swapped frame direction.
53
+ */
54
+ export const quatConjugate = (value) => asQuaternion(-value[0], -value[1], -value[2], value[3]);
55
+ /**
56
+ * Computes squared quaternion norm.
57
+ *
58
+ * @param value Input quaternion.
59
+ * @returns Squared norm.
60
+ */
61
+ export const quatNormSquared = (value) => value[0] * value[0] +
62
+ value[1] * value[1] +
63
+ value[2] * value[2] +
64
+ value[3] * value[3];
65
+ /**
66
+ * Computes quaternion norm.
67
+ *
68
+ * @param value Input quaternion.
69
+ * @returns Euclidean norm.
70
+ */
71
+ export const quatNorm = (value) => Math.sqrt(quatNormSquared(value));
72
+ /**
73
+ * Normalizes quaternion length to 1.
74
+ *
75
+ * Unsafe variant: performs no zero-length guard.
76
+ * Degenerate inputs can yield `NaN`/`Infinity`.
77
+ *
78
+ * @param value Quaternion to normalize.
79
+ * @returns Unit quaternion.
80
+ */
81
+ export const quatNormalizeUnsafe = (value) => {
82
+ const norm = quatNorm(value);
83
+ return asQuaternion(value[0] / norm, value[1] / norm, value[2] / norm, value[3] / norm);
84
+ };
85
+ /**
86
+ * Normalizes quaternion length to 1.
87
+ *
88
+ * Throws when quaternion norm is zero.
89
+ *
90
+ * @param value Quaternion to normalize.
91
+ * @returns Unit quaternion.
92
+ * @throws {Error} When the quaternion is near zero length.
93
+ */
94
+ export const quatNormalize = (value) => {
95
+ const norm = quatNorm(value);
96
+ if (norm <= NEAR_ZERO) {
97
+ throw new Error('Cannot normalize a zero-length quaternion');
98
+ }
99
+ return quatNormalizeUnsafe(value);
100
+ };
101
+ /**
102
+ * Computes quaternion inverse.
103
+ *
104
+ * Unsafe variant: performs no zero-length guard.
105
+ * Degenerate inputs can yield `NaN`/`Infinity`.
106
+ *
107
+ * @param value Quaternion to invert.
108
+ * @returns Inverse quaternion in swapped frame direction.
109
+ */
110
+ export const quatInverseUnsafe = (value) => {
111
+ const normSquared = quatNormSquared(value);
112
+ const conjugate = quatConjugate(value);
113
+ return asQuaternion(conjugate[0] / normSquared, conjugate[1] / normSquared, conjugate[2] / normSquared, conjugate[3] / normSquared);
114
+ };
115
+ /**
116
+ * Computes quaternion inverse.
117
+ *
118
+ * Throws when quaternion norm is zero.
119
+ *
120
+ * @param value Quaternion to invert.
121
+ * @returns Inverse quaternion in swapped frame direction.
122
+ * @throws {Error} When the quaternion is near zero length.
123
+ */
124
+ export const quatInverse = (value) => {
125
+ const normSquared = quatNormSquared(value);
126
+ if (normSquared <= NEAR_ZERO * NEAR_ZERO) {
127
+ throw new Error('Cannot invert a zero-length quaternion');
128
+ }
129
+ return quatInverseUnsafe(value);
130
+ };
131
+ /**
132
+ * Composes two frame-compatible quaternions in chain order.
133
+ *
134
+ * `composeQuats(outer, inner)` returns `outer * inner`, so `inner` is applied
135
+ * first.
136
+ *
137
+ * @param outer Outer rotation.
138
+ * @param inner Inner rotation.
139
+ * @returns Composed rotation `outer * inner`.
140
+ */
141
+ export const composeQuats = (outer, inner) => {
142
+ const [x1, y1, z1, w1] = inner;
143
+ const [x2, y2, z2, w2] = outer;
144
+ const x = w2 * x1 +
145
+ x2 * w1 +
146
+ y2 * z1 -
147
+ z2 * y1;
148
+ const y = w2 * y1 -
149
+ x2 * z1 +
150
+ y2 * w1 +
151
+ z2 * x1;
152
+ const z = w2 * z1 +
153
+ x2 * y1 -
154
+ y2 * x1 +
155
+ z2 * w1;
156
+ const w = w2 * w1 -
157
+ x2 * x1 -
158
+ y2 * y1 -
159
+ z2 * z1;
160
+ return asQuaternion(x, y, z, w);
161
+ };
162
+ export function rotateVec3ByQuatUnsafe(rotation, value) {
163
+ const [qx, qy, qz, qw] = quatNormalizeUnsafe(rotation);
164
+ const [vx, vy, vz] = value;
165
+ // Quaternion-vector rotation via optimized form:
166
+ // t = 2 * cross(q.xyz, v), v' = v + qw * t + cross(q.xyz, t)
167
+ const tx = 2 * (qy * vz -
168
+ qz * vy);
169
+ const ty = 2 * (qz * vx -
170
+ qx * vz);
171
+ const tz = 2 * (qx * vy -
172
+ qy * vx);
173
+ const rotatedX = vx +
174
+ qw * tx +
175
+ (qy * tz - qz * ty);
176
+ const rotatedY = vy +
177
+ qw * ty +
178
+ (qz * tx - qx * tz);
179
+ const rotatedZ = vz +
180
+ qw * tz +
181
+ (qx * ty - qy * tx);
182
+ return [
183
+ asQuantity(rotatedX),
184
+ asQuantity(rotatedY),
185
+ asQuantity(rotatedZ),
186
+ ];
187
+ }
188
+ export function rotateVec3ByQuat(rotation, value) {
189
+ quatNormalize(rotation);
190
+ return rotateVec3ByQuatUnsafe(rotation, value);
191
+ }
192
+ /**
193
+ * Creates a quaternion from axis-angle representation.
194
+ *
195
+ * Axis is normalized internally.
196
+ * Unsafe variant: performs no zero-length guard for `axis`.
197
+ *
198
+ * @param frameTag Frame token.
199
+ * @param axis Rotation axis.
200
+ * @param angleRadians Rotation angle in radians.
201
+ * @returns Quaternion in `<Frame, Frame>` order.
202
+ */
203
+ export const quatFromAxisAngleUnsafe = (frameTag, axis, angleRadians) => {
204
+ void frameTag;
205
+ const normalizedAxis = normalizeVec3Unsafe(axis);
206
+ const halfAngle = angleRadians * 0.5;
207
+ const sinHalfAngle = Math.sin(halfAngle);
208
+ const cosHalfAngle = Math.cos(halfAngle);
209
+ return asQuaternion(normalizedAxis[0] * sinHalfAngle, normalizedAxis[1] * sinHalfAngle, normalizedAxis[2] * sinHalfAngle, cosHalfAngle);
210
+ };
211
+ /**
212
+ * Creates a quaternion from axis-angle representation.
213
+ *
214
+ * Axis is normalized internally.
215
+ * Throws when axis has zero length.
216
+ *
217
+ * @param frameTag Frame token.
218
+ * @param axis Rotation axis.
219
+ * @param angleRadians Rotation angle in radians.
220
+ * @returns Quaternion in `<Frame, Frame>` order.
221
+ * @throws {Error} When `axis` is near zero length.
222
+ */
223
+ export const quatFromAxisAngle = (frameTag, axis, angleRadians) => {
224
+ normalizeVec3(axis);
225
+ return quatFromAxisAngleUnsafe(frameTag, axis, angleRadians);
226
+ };
227
+ /**
228
+ * Builds a frame-local quaternion from Euler angles and explicit axis order.
229
+ *
230
+ * Rotations are composed in intrinsic order: the `order` string describes
231
+ * which axis is applied first (leftmost) through last (rightmost). For example
232
+ * `'ZYX'` applies Z first, then Y, then X.
233
+ *
234
+ * @param frameTag Frame token.
235
+ * @param xRadians Rotation around X axis in radians.
236
+ * @param yRadians Rotation around Y axis in radians.
237
+ * @param zRadians Rotation around Z axis in radians.
238
+ * @param order Euler axis composition order.
239
+ * @returns Quaternion in `<Frame, Frame>` order.
240
+ */
241
+ export const quatFromEulerUnsafe = (frameTag, xRadians, yRadians, zRadians, order = 'ZYX') => {
242
+ const makeAxisQuat = (axis) => {
243
+ const angle = axis === 'X' ? xRadians : axis === 'Y' ? yRadians : zRadians;
244
+ const half = angle * 0.5;
245
+ const sinHalf = Math.sin(half);
246
+ const cosHalf = Math.cos(half);
247
+ if (axis === 'X') {
248
+ return asQuaternion(sinHalf, 0, 0, cosHalf);
249
+ }
250
+ if (axis === 'Y') {
251
+ return asQuaternion(0, sinHalf, 0, cosHalf);
252
+ }
253
+ return asQuaternion(0, 0, sinHalf, cosHalf);
254
+ };
255
+ let quat_result = quatIdentity(frameTag);
256
+ for (let index = 0; index < order.length; index += 1) {
257
+ const axis = order[index];
258
+ quat_result = composeQuats(makeAxisQuat(axis), quat_result);
259
+ }
260
+ return quatNormalizeUnsafe(quat_result);
261
+ };
262
+ /**
263
+ * Builds a frame-local quaternion from Euler angles and explicit axis order.
264
+ *
265
+ * Rotations are composed in intrinsic order: the `order` string describes
266
+ * which axis is applied first (leftmost) through last (rightmost). For example
267
+ * `'ZYX'` applies Z first, then Y, then X.
268
+ *
269
+ * @param frameTag Frame token.
270
+ * @param xRadians Rotation around X axis in radians.
271
+ * @param yRadians Rotation around Y axis in radians.
272
+ * @param zRadians Rotation around Z axis in radians.
273
+ * @param order Euler axis composition order.
274
+ * @returns Normalized quaternion in `<Frame, Frame>` order.
275
+ */
276
+ export const quatFromEuler = (frameTag, xRadians, yRadians, zRadians, order = 'ZYX') => {
277
+ const quat_result = quatFromEulerUnsafe(frameTag, xRadians, yRadians, zRadians, order);
278
+ return quatNormalize(quat_result);
279
+ };
280
+ /**
281
+ * Normalized linear interpolation with shortest-path hemisphere selection.
282
+ *
283
+ * @param start Start quaternion.
284
+ * @param end End quaternion.
285
+ * @param t Interpolation parameter.
286
+ * @returns Interpolated normalized quaternion.
287
+ */
288
+ export const quatNlerpUnsafe = (start, end, t) => {
289
+ let endX = end[0];
290
+ let endY = end[1];
291
+ let endZ = end[2];
292
+ let endW = end[3];
293
+ const dot = start[0] * endX +
294
+ start[1] * endY +
295
+ start[2] * endZ +
296
+ start[3] * endW;
297
+ if (dot < 0) {
298
+ endX = -endX;
299
+ endY = -endY;
300
+ endZ = -endZ;
301
+ endW = -endW;
302
+ }
303
+ const inverseT = 1 - t;
304
+ return quatNormalizeUnsafe(asQuaternion(start[0] * inverseT +
305
+ endX * t, start[1] * inverseT +
306
+ endY * t, start[2] * inverseT +
307
+ endZ * t, start[3] * inverseT +
308
+ endW * t));
309
+ };
310
+ /**
311
+ * Normalized linear interpolation with shortest-path hemisphere selection.
312
+ *
313
+ * @param start Start quaternion.
314
+ * @param end End quaternion.
315
+ * @param t Interpolation parameter.
316
+ * @returns Interpolated normalized quaternion.
317
+ */
318
+ export const quatNlerp = (start, end, t) => {
319
+ let endX = end[0];
320
+ let endY = end[1];
321
+ let endZ = end[2];
322
+ let endW = end[3];
323
+ const dot = start[0] * endX +
324
+ start[1] * endY +
325
+ start[2] * endZ +
326
+ start[3] * endW;
327
+ if (dot < 0) {
328
+ endX = -endX;
329
+ endY = -endY;
330
+ endZ = -endZ;
331
+ endW = -endW;
332
+ }
333
+ const inverseT = 1 - t;
334
+ const quat_blend = asQuaternion(start[0] * inverseT +
335
+ endX * t, start[1] * inverseT +
336
+ endY * t, start[2] * inverseT +
337
+ endZ * t, start[3] * inverseT +
338
+ endW * t);
339
+ return quatNormalize(quat_blend);
340
+ };
341
+ /**
342
+ * Spherical interpolation with shortest-path hemisphere selection.
343
+ *
344
+ * @param start Start quaternion.
345
+ * @param end End quaternion.
346
+ * @param t Interpolation parameter.
347
+ * @returns Interpolated normalized quaternion.
348
+ */
349
+ export const quatSlerpUnsafe = (start, end, t) => {
350
+ let endX = end[0];
351
+ let endY = end[1];
352
+ let endZ = end[2];
353
+ let endW = end[3];
354
+ let cosine = start[0] * endX +
355
+ start[1] * endY +
356
+ start[2] * endZ +
357
+ start[3] * endW;
358
+ if (cosine < 0) {
359
+ cosine = -cosine;
360
+ endX = -endX;
361
+ endY = -endY;
362
+ endZ = -endZ;
363
+ endW = -endW;
364
+ }
365
+ if (cosine > 0.9995) {
366
+ return quatNlerpUnsafe(start, asQuaternion(endX, endY, endZ, endW), t);
367
+ }
368
+ const theta0 = Math.acos(Math.max(-1, Math.min(1, cosine)));
369
+ const sinTheta0 = Math.sin(theta0);
370
+ const theta = theta0 * t;
371
+ const sinTheta = Math.sin(theta);
372
+ const s0 = Math.sin(theta0 - theta) / sinTheta0;
373
+ const s1 = sinTheta / sinTheta0;
374
+ return quatNormalizeUnsafe(asQuaternion(s0 * start[0] +
375
+ s1 * endX, s0 * start[1] +
376
+ s1 * endY, s0 * start[2] +
377
+ s1 * endZ, s0 * start[3] +
378
+ s1 * endW));
379
+ };
380
+ /**
381
+ * Spherical interpolation with shortest-path hemisphere selection.
382
+ *
383
+ * @param start Start quaternion.
384
+ * @param end End quaternion.
385
+ * @param t Interpolation parameter.
386
+ * @returns Interpolated normalized quaternion.
387
+ */
388
+ export const quatSlerp = (start, end, t) => {
389
+ let endX = end[0];
390
+ let endY = end[1];
391
+ let endZ = end[2];
392
+ let endW = end[3];
393
+ let cosine = start[0] * endX +
394
+ start[1] * endY +
395
+ start[2] * endZ +
396
+ start[3] * endW;
397
+ if (cosine < 0) {
398
+ cosine = -cosine;
399
+ endX = -endX;
400
+ endY = -endY;
401
+ endZ = -endZ;
402
+ endW = -endW;
403
+ }
404
+ if (cosine > 0.9995) {
405
+ return quatNlerp(start, asQuaternion(endX, endY, endZ, endW), t);
406
+ }
407
+ const theta0 = Math.acos(Math.max(-1, Math.min(1, cosine)));
408
+ const sinTheta0 = Math.sin(theta0);
409
+ const theta = theta0 * t;
410
+ const sinTheta = Math.sin(theta);
411
+ const s0 = Math.sin(theta0 - theta) / sinTheta0;
412
+ const s1 = sinTheta / sinTheta0;
413
+ const quat_blend = asQuaternion(s0 * start[0] +
414
+ s1 * endX, s0 * start[1] +
415
+ s1 * endY, s0 * start[2] +
416
+ s1 * endZ, s0 * start[3] +
417
+ s1 * endW);
418
+ return quatNormalize(quat_blend);
419
+ };