36 lines
2.7 KiB
JavaScript
36 lines
2.7 KiB
JavaScript
import assert from 'node:assert/strict';
|
|
import * as THREE from 'three';
|
|
import { ArchiveVisibility } from '../src/archive-visibility.ts';
|
|
const visibility=new ArchiveVisibility();
|
|
const summaries=[];
|
|
for(const [width,height] of [[1920,1080],[2560,1080],[3840,1080],[1400,1050],[1080,1920]])for(const detail of [false,true]) {
|
|
const camera=new THREE.PerspectiveCamera(3.0,width/height,5,300);
|
|
const direction=new THREE.Vector3(...(detail?[-.277,.238,.931]:[-.81,.326,.487])).normalize();
|
|
const distance=detail?72:140;
|
|
const span=detail?5.9:width<height?12:7.33;
|
|
camera.fov=THREE.MathUtils.radToDeg(2*Math.atan(span/(2*distance)));
|
|
camera.position.copy(direction.multiplyScalar(distance));camera.lookAt(0,0,0);camera.updateProjectionMatrix();camera.updateMatrixWorld();
|
|
const candidates=visibility.update(camera,distance+25,0,0,false);
|
|
const selected=candidates.filter(c=>visibility.intersects((c.lane-2)*5.2,-4.6,(c.row-15.5)*.62));
|
|
const keys=new Set(selected.map(c=>`${c.lane}:${c.row}`));assert.equal(keys.size,selected.length);
|
|
// Independently scan a much larger reference lattice. Every intersecting card
|
|
// must have been generated by the projected footprint, at both extreme lifts.
|
|
const candidateKeys=new Set(candidates.map(c=>`${c.lane}:${c.row}`));
|
|
const viewProjection=new THREE.Matrix4().multiplyMatrices(camera.projectionMatrix,camera.matrixWorldInverse);
|
|
for(const y of [-6,1.6])for(let lane=-30;lane<=30;lane++)for(let row=-180;row<=180;row++) {
|
|
for(const dx of [-2.5,0,2.5])for(const dy of [0,1.85,3.7])for(const dz of [-.3,.3]) {
|
|
const point=new THREE.Vector3((lane-2)*5.2+dx,y+dy,(row-15.5)*.62+dz);
|
|
const depth=-point.clone().applyMatrix4(camera.matrixWorldInverse).z;
|
|
point.applyMatrix4(viewProjection);
|
|
if(Math.abs(point.x)<=1.18&&Math.abs(point.y)<=1.18&&depth>=5&&depth<=distance+33)assert.ok(candidateKeys.has(`${lane}:${row}`),`Missing ${width}x${height} ${lane}:${row} y=${y}`);
|
|
}
|
|
}
|
|
const extra=visibility.update(camera,distance+25,0,0,true).filter(c=>visibility.intersects((c.lane-2)*5.2,-4.6,(c.row-15.5)*.62));
|
|
assert.ok(extra.length>=selected.length);
|
|
const shifted=visibility.update(camera,distance+25,52,-6.2,false).filter(c=>visibility.intersects((c.lane-2)*5.2-52,-4.6,(c.row-15.5)*.62-6.2));
|
|
assert.equal(shifted.length,selected.length,'Whole-cell track movement preserves view coverage');
|
|
summaries.push({width,height,detail,drawn:selected.length,candidates:candidates.length,extra:extra.length});
|
|
}
|
|
assert.ok(summaries[4].drawn>summaries[0].drawn,'Wider view increases archive count');
|
|
console.table(summaries);console.log('Projected coverage, extreme heights, unique picking cells, overscan and track translation passed.');
|