import test from 'node:test'; import assert from 'node:assert/strict'; import { Matrix4, Vector3 } from 'three'; import { sourceAnchorSupportGeometry } from './source-anchor-support.mjs'; import { descriptorSourceMatrix } from './environment-assembly.mjs'; test('support OBJ and nav use the ROS reflected-Z bridge and upward floor winding', () => { const placement = { translation: [10, 20, 30], rotation: [0, 0, 0, 1], scale: [1, 1, 1] }; const obj = sourceAnchorSupportGeometry([[12, 25, 60]], placement, { halfExtent: 1, thickness: 2 }); const nav = sourceAnchorSupportGeometry([[12, 25, 60]], placement, { halfExtent: 1, thickness: 2, metersPerSourceUnit: 0.1 }); assert.deepEqual(obj.positions.slice(0, 3), [1, 5, -29]); assert.ok(nav.navigationPositions.every((v, i) => Math.abs(v - obj.navigationPositions[i] * 0.1) < 1e-12)); const [a, b, c] = obj.indices.slice(0, 3).map(i => new Vector3().fromArray(obj.positions, i * 3)); assert.ok(b.sub(a).cross(c.sub(a)).y > 0); }); test('rotated nonuniform primary placements preserve the source support footprint', () => { const placement = { translation: [10, 20, 30], rotation: [0, Math.sin(0.4), 0, Math.cos(0.4)], scale: [2, 3, 4] }; const geometry = sourceAnchorSupportGeometry([[12, 25, 60]], placement, { halfExtent: 1, thickness: 2, metersPerSourceUnit: 0.1 }); const toSource = descriptorSourceMatrix(placement).multiply(new Matrix4().makeScale(10, 10, -10)); const first = new Vector3().fromArray(geometry.positions).applyMatrix4(toSource); assert.ok(first.distanceTo(new Vector3(11, 25, 59)) < 1e-10); assert.equal(geometry.indices.length, 36); assert.equal(geometry.navigationPositions.length, 18); }); test('a reviewed native-ground omission removes the same footprint from mesh and nav', () => { const placement = { translation: [0, 0, 0], rotation: [0, 0, 0, 1], scale: [1, 1, 1] }; const result = sourceAnchorSupportGeometry([[0, 0, 1], [20, 0, 2]], placement, { omitPointIndices: [0] }); assert.equal(result.positions.length, 24); assert.equal(result.indices.length, 36); assert.equal(result.navigationPositions.length, 18); assert.ok(result.positions.filter((_, i) => i % 3 === 0).every(x => x === -40 || x === 80)); assert.throws(() => sourceAnchorSupportGeometry([[0, 0, 1]], placement, { omitPointIndices: [1] }), /omissions/); });