diff --git a/CHANGELOG.md b/CHANGELOG.md
index e0c9b663e1a7e1914a30bdfb326e5ba7adfaa24d..09efd6e9e1ff454dfaba15877d94a07fafcbb44c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,7 @@ Note that since we don't clearly distinguish between a public and private interf
## [Unreleased]
+- Add principal axes spec and fix edge cases
- Add a uniform color theme for NtC tube that still paints residue and segment dividers in a different color
- Mesh exporter improvements
- Support points & lines in glTF export
diff --git a/src/mol-math/linear-algebra/3d/vec3.ts b/src/mol-math/linear-algebra/3d/vec3.ts
index d39cbba843d79881eea6e8151cee67217e1cd040..294fd5a9c354ed19d3245d0e33ad81c1490ac0e5 100644
--- a/src/mol-math/linear-algebra/3d/vec3.ts
+++ b/src/mol-math/linear-algebra/3d/vec3.ts
@@ -1,5 +1,5 @@
/**
- * Copyright (c) 2017-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ * Copyright (c) 2017-2023 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author David Sehnal <david.sehnal@gmail.com>
* @author Alexander Rose <alexander.rose@weirdbyte.de>
@@ -24,6 +24,8 @@ import { Mat3 } from './mat3';
import { Quat } from './quat';
import { EPSILON } from './common';
+const _isFinite = isFinite;
+
export { ReadonlyVec3 };
interface Vec3 extends Array<number> { [d: number]: number, '@type': 'vec3', length: 3 }
@@ -48,6 +50,10 @@ namespace Vec3 {
return out;
}
+ export function isFinite(a: Vec3): boolean {
+ return _isFinite(a[0]) && _isFinite(a[1]) && _isFinite(a[2]);
+ }
+
export function hasNaN(a: Vec3) {
return isNaN(a[0]) || isNaN(a[1]) || isNaN(a[2]);
}
@@ -636,4 +642,4 @@ namespace Vec3 {
export const negUnitZ: ReadonlyVec3 = create(0, 0, -1);
}
-export { Vec3 };
\ No newline at end of file
+export { Vec3 };
diff --git a/src/mol-math/linear-algebra/_spec/principal-axes.spec.ts b/src/mol-math/linear-algebra/_spec/principal-axes.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..6a866bd483f68ea05edab08d0584d99425078d3a
--- /dev/null
+++ b/src/mol-math/linear-algebra/_spec/principal-axes.spec.ts
@@ -0,0 +1,19 @@
+/**
+ * Copyright (c) 2023 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author Gianluca Tomasello <giagitom@gmail.com>
+ */
+
+import { NumberArray } from '../../../mol-util/type-helpers';
+import { PrincipalAxes } from '../matrix/principal-axes';
+
+describe('PrincipalAxes', () => {
+ it('same-cartesian-plane', () => {
+ const positions: NumberArray = [ // same y coordinate
+ 0.1945, -0.0219, -0.0416,
+ -0.0219, -0.0219, -0.0119,
+ ];
+ const { origin } = PrincipalAxes.ofPositions(positions).boxAxes;
+ expect(origin[0] !== Infinity && origin[1] !== Infinity && origin[2] !== Infinity).toBe(true);
+ });
+});
diff --git a/src/mol-math/linear-algebra/matrix/principal-axes.ts b/src/mol-math/linear-algebra/matrix/principal-axes.ts
index 90091e1e123a20a112fb2439edf4ef1f9982e163..79fcc46f05bf57369d1951e727183ed15ff1fed9 100644
--- a/src/mol-math/linear-algebra/matrix/principal-axes.ts
+++ b/src/mol-math/linear-algebra/matrix/principal-axes.ts
@@ -1,7 +1,8 @@
/**
- * Copyright (c) 2018-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ * Copyright (c) 2018-2023 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
+ * @author Gianluca Tomasello <giagitom@gmail.com>
*/
import { Matrix } from './matrix';
@@ -123,12 +124,17 @@ namespace PrincipalAxes {
const dirB = Vec3.setMagnitude(Vec3(), a.dirB, (d2a + d2b) / 2);
const dirC = Vec3.setMagnitude(Vec3(), a.dirC, (d3a + d3b) / 2);
+ const okDirA = Vec3.isFinite(dirA);
+ const okDirB = Vec3.isFinite(dirB);
+ const okDirC = Vec3.isFinite(dirC);
+
const origin = Vec3();
const addCornerHelper = function (d1: number, d2: number, d3: number) {
Vec3.copy(tmpBoxVec, center);
- Vec3.scaleAndAdd(tmpBoxVec, tmpBoxVec, a.dirA, d1);
- Vec3.scaleAndAdd(tmpBoxVec, tmpBoxVec, a.dirB, d2);
- Vec3.scaleAndAdd(tmpBoxVec, tmpBoxVec, a.dirC, d3);
+
+ if (okDirA) Vec3.scaleAndAdd(tmpBoxVec, tmpBoxVec, a.dirA, d1);
+ if (okDirB) Vec3.scaleAndAdd(tmpBoxVec, tmpBoxVec, a.dirB, d2);
+ if (okDirC) Vec3.scaleAndAdd(tmpBoxVec, tmpBoxVec, a.dirC, d3);
Vec3.add(origin, origin, tmpBoxVec);
};
addCornerHelper(d1a, d2a, d3a);