Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | 128x 128x | import { vec3 } from 'gl-matrix';
import type { IImageVolume, Point3 } from '../../../types';
export type IndexMajorAxis = { axis: 0 | 1 | 2; sign: 1 | -1 };
export const SOURCE_SLICE_INDEX_TOLERANCE = 1e-4;
export const NEAREST_VOXEL_TIE_EPSILON = 1e-6;
function dot(a: Point3, b: Point3): number {
return vec3.dot(a as unknown as vec3, b as unknown as vec3);
}
export function getIndexMajorAxis(
volume: IImageVolume,
worldVector: Point3,
majorThreshold = 0.995
): IndexMajorAxis | undefined {
const row = volume.direction.slice(0, 3) as Point3;
const col = volume.direction.slice(3, 6) as Point3;
const scan = volume.direction.slice(6, 9) as Point3;
const components = [
dot(worldVector, row),
dot(worldVector, col),
dot(worldVector, scan),
] as [number, number, number];
const absComponents = components.map((value) => Math.abs(value)) as [
number,
number,
number,
];
const maxValue = Math.max(...absComponents);
const axis = absComponents.indexOf(maxValue) as 0 | 1 | 2;
if (maxValue < majorThreshold) {
return;
}
const secondary = absComponents
.filter((_value, index) => index !== axis)
.some((value) => value > 1 - majorThreshold);
if (secondary) {
return;
}
return {
axis,
sign: components[axis] >= 0 ? 1 : -1,
};
}
export function getSpatiallyClampedContinuousCoordinate(
dimension: number,
value: number
): number | undefined {
const upperBound = dimension - 0.5;
if (
value < -0.5 - SOURCE_SLICE_INDEX_TOLERANCE ||
value > upperBound + SOURCE_SLICE_INDEX_TOLERANCE
) {
return;
}
return Math.min(dimension - 1, Math.max(0, value));
}
export function getNearestVoxelIndex(continuousIndex: number): number {
return Math.floor(continuousIndex + 0.5 - NEAREST_VOXEL_TIE_EPSILON);
}
export function getSpatiallyClampedContinuousIndex(
dimensions: Point3,
continuousIndex: Point3
): Point3 | undefined {
const clampedIndex = [0, 0, 0] as Point3;
for (let axis = 0; axis < 3; axis++) {
const clampedCoordinate = getSpatiallyClampedContinuousCoordinate(
dimensions[axis],
continuousIndex[axis]
);
if (clampedCoordinate === undefined) {
return;
}
clampedIndex[axis] = clampedCoordinate;
}
return clampedIndex;
}
|