Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 83 additions & 0 deletions src/utils/visibility.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import { describe, it, expect } from 'vitest';
import { PerspectiveCamera } from 'three';
import { calcLabelVisibility } from './visibility';

describe('calcLabelVisibility', () => {
const nodePosition = { x: 0, y: 0, z: 0 };
const camera = new PerspectiveCamera();
camera.position.z = 10000;
camera.zoom = 1;

it('should always show labels when labelType is "all"', () => {
const fn = calcLabelVisibility({ nodeCount: 1, labelType: 'all' });
expect(fn('node', 1)).toBe(true);
expect(fn('edge', 1)).toBe(true);
});

it('should always show node labels when labelType is "nodes"', () => {
const fn = calcLabelVisibility({ nodeCount: 1, labelType: 'nodes' });
expect(fn('node', 1)).toBe(true);
expect(fn('edge', 1)).toBe(false);
});

it('should always show edge labels when labelType is "edges"', () => {
const fn = calcLabelVisibility({ nodeCount: 1, labelType: 'edges' });
expect(fn('node', 1)).toBe(false);
expect(fn('edge', 1)).toBe(true);
});

it('should never show labels when labelType is "none"', () => {
const fn = calcLabelVisibility({ nodeCount: 1, labelType: 'none' });
expect(fn('node', 1)).toBe(false);
expect(fn('edge', 1)).toBe(false);
});

it('should show node label in "auto" if size > 7', () => {
const fn = calcLabelVisibility({ nodeCount: 1, labelType: 'auto' });
expect(fn('node', 8)).toBe(true);
});

it('should show node label in "auto" if camera is close', () => {
const closeCamera = new PerspectiveCamera();
closeCamera.position.z = 1000;
closeCamera.zoom = 1;
const fn = calcLabelVisibility({
nodeCount: 1,
labelType: 'auto',
nodePosition,
camera: closeCamera
});
expect(fn('node', 1)).toBe(true);
});

it('should not show node label in "auto" if size <= 7 and camera is far', () => {
const fn = calcLabelVisibility({
nodeCount: 1,
labelType: 'auto',
nodePosition,
camera
});
expect(fn('node', 1)).toBe(false);
});

it('should not show edge label in "auto"', () => {
const fn = calcLabelVisibility({ nodeCount: 1, labelType: 'auto' });
expect(fn('edge', 1)).toBe(false);
});

it('should hide label if camera is far and not always visible', () => {
const fn = calcLabelVisibility({
nodeCount: 1,
labelType: 'auto',
nodePosition,
camera
});
expect(fn('node', 1)).toBe(false);
});

it('should not throw if camera or nodePosition is undefined', () => {
const fn = calcLabelVisibility({ nodeCount: 1, labelType: 'auto' });
expect(fn('node', 1)).toBe(false);
expect(fn('edge', 1)).toBe(false);
});
});
13 changes: 7 additions & 6 deletions src/utils/visibility.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,25 +11,26 @@ interface CalcLabelVisibilityArgs {
}

export function calcLabelVisibility({
nodeCount,
nodePosition,
labelType,
camera
}: CalcLabelVisibilityArgs) {
return (shape: 'node' | 'edge', size: number) => {
const isAlwaysVisible =
labelType === 'all' ||
(labelType === 'nodes' && shape === 'node') ||
(labelType === 'edges' && shape === 'edge');

if (
!isAlwaysVisible &&
camera &&
nodePosition &&
camera?.position?.z / camera?.zoom - nodePosition?.z > 6000
) {
return false;
}

if (labelType === 'all') {
return true;
} else if (labelType === 'nodes' && shape === 'node') {
return true;
} else if (labelType === 'edges' && shape === 'edge') {
if (isAlwaysVisible) {
return true;
} else if (labelType === 'auto' && shape === 'node') {
if (size > 7) {
Expand Down