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:widthvisibility.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.');