Back to home page

EIC code displayed by LXR

 
 

    


Warning, /firebird/packages/firebird-core/src/painters/batched-trajectory.painter.spec.ts is written in an unsupported language. File is not indexed.

0001 import { Group } from 'three';
0002 import { BatchedTrajectoryPainter } from './batched-trajectory.painter';
0003 import { PointTrajectoryPiece } from '../model/point-trajectory.piece';
0004 import { entityRefOf } from './event-piece-painter';
0005 
0006 describe('BatchedTrajectoryPainter', () => {
0007   let mockParentNode: Group;
0008   let piece: PointTrajectoryPiece;
0009 
0010   beforeEach(() => {
0011     mockParentNode = new Group();
0012     vi.spyOn(mockParentNode, 'add');
0013     vi.spyOn(mockParentNode, 'remove');
0014 
0015     piece = new PointTrajectoryPiece('TestTrajectories');
0016     piece.pointColumns = ['x', 'y', 'z', 't'];
0017     piece.count = 3;
0018     piece.columns = {
0019       pdg: [11, 22, 2212], // electron (solid), gamma (dashed), proton (solid)
0020       charge: [-1, 0, 1],
0021     };
0022     piece.points = [
0023       [[0, 0, 0, 10], [10, 0, 0, 20]],                      // 1 segment,  t=10
0024       [[0, 10, 0, 15], [10, 10, 0, 25], [20, 10, 0, 35]],   // 2 segments, t=15,25
0025       [[0, 20, 0, 40], [10, 20, 0, 50]],                    // 1 segment,  t=40
0026     ];
0027   });
0028 
0029   it('builds one solid and one dashed batch covering all segments', () => {
0030     const painter = new BatchedTrajectoryPainter(mockParentNode, piece);
0031     const batches = (painter as any).batches;
0032     expect(batches.length).toBe(2);
0033     const solid = batches.find((b: any) => !b.dashed);
0034     const dashed = batches.find((b: any) => b.dashed);
0035     // electron 1 + proton 1 segments solid; gamma 2 segments dashed
0036     expect(solid.count).toBe(2);
0037     expect(dashed.count).toBe(3 - 1); // gamma has 3 points -> 2 segments
0038     expect(mockParentNode.add).toHaveBeenCalledTimes(2);
0039   });
0040 
0041   it('sorts segments by start time and cuts with instanceCount', () => {
0042     const painter = new BatchedTrajectoryPainter(mockParentNode, piece);
0043     const batches = (painter as any).batches;
0044     for (const batch of batches) {
0045       for (let i = 1; i < batch.count; i++) {
0046         expect(batch.startTimes[i]).toBeGreaterThanOrEqual(batch.startTimes[i - 1]);
0047       }
0048     }
0049 
0050     const solid = batches.find((b: any) => !b.dashed);
0051     const dashed = batches.find((b: any) => b.dashed);
0052 
0053     painter.paint(5); // before everything
0054     expect(solid.geometry.instanceCount).toBe(0);
0055     expect(dashed.geometry.instanceCount).toBe(0);
0056 
0057     painter.paint(30); // electron segment (t=10) + gamma segments (t=15, 25)
0058     expect(solid.geometry.instanceCount).toBe(1);
0059     expect(dashed.geometry.instanceCount).toBe(2);
0060 
0061     painter.paint(null); // timeless: everything
0062     expect(solid.geometry.instanceCount).toBe(solid.count);
0063     expect(dashed.geometry.instanceCount).toBe(dashed.count);
0064   });
0065 
0066   it('resolves a picked segment to its trajectory through entityRefOf', () => {
0067     const painter = new BatchedTrajectoryPainter(mockParentNode, piece);
0068     const dashed = (painter as any).batches.find((b: any) => b.dashed);
0069     // Every dashed segment belongs to the gamma (trajectory id 1)
0070     const ref = entityRefOf(dashed.object, { faceIndex: 0 });
0071     expect(ref).toEqual({ pieceName: 'TestTrajectories', entityIndex: 1 });
0072   });
0073 
0074   it('recolors a track for highlight and restores it after', () => {
0075     const painter = new BatchedTrajectoryPainter(mockParentNode, piece);
0076     const solid = (painter as any).batches.find((b: any) => !b.dashed);
0077     const protonSegment = [...solid.trackIds].indexOf(2);
0078     const before = solid.colors.slice(protonSegment * 6, protonSegment * 6 + 3);
0079 
0080     painter.highlightEntity(2);
0081     const highlighted = solid.colors.slice(protonSegment * 6, protonSegment * 6 + 3);
0082     expect([...highlighted]).not.toEqual([...before]);
0083 
0084     painter.unhighlightEntity(2);
0085     const restored = solid.colors.slice(protonSegment * 6, protonSegment * 6 + 3);
0086     expect([...restored].map(v => v.toFixed(5))).toEqual([...before].map(v => v.toFixed(5)));
0087   });
0088 
0089   it('keeps one highlight when another track is highlighted (selection plus hover)', () => {
0090     const painter = new BatchedTrajectoryPainter(mockParentNode, piece);
0091     const solid = (painter as any).batches.find((b: any) => !b.dashed);
0092     const segmentOf = (track: number) => [...solid.trackIds].indexOf(track);
0093     const rgb = (track: number) => [...solid.colors.slice(segmentOf(track) * 6, segmentOf(track) * 6 + 3)]
0094       .map((v: number) => v.toFixed(5));
0095     const electronBefore = rgb(0);
0096 
0097     painter.highlightEntity(2); // selected
0098     const protonHighlighted = rgb(2);
0099     painter.highlightEntity(0); // hovered
0100     expect(rgb(2)).toEqual(protonHighlighted);
0101     expect(rgb(0)).toEqual(protonHighlighted);
0102 
0103     painter.unhighlightEntity(0); // hover ends, selection stays
0104     expect(rgb(2)).toEqual(protonHighlighted);
0105     expect(rgb(0)).toEqual(electronBefore);
0106   });
0107 
0108   it('disposes both batch objects', () => {
0109     const painter = new BatchedTrajectoryPainter(mockParentNode, piece);
0110     painter.dispose();
0111     expect((painter as any).batches.length).toBe(0);
0112     expect(mockParentNode.remove).toHaveBeenCalledTimes(2);
0113   });
0114 });