Initial commit: RHINE LAB · ANALYSIS OS:三维界面与动效实验(本仓库不含个人归档索引数据)
This commit is contained in:
@@ -0,0 +1,35 @@
|
||||
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.');
|
||||
Reference in New Issue
Block a user