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 94 95 96 97 98 99 100 101 102 103 104 105 | 1x | import vtkMath from '@kitware/vtk.js/Common/Core/Math'; import { utilities as csUtils } from '@cornerstonejs/core'; import type { Types } from '@cornerstonejs/core'; /** * Returns a point based on some criteria (e.g., minimum or maximum intensity) in * the line of sight (on the line between the passed worldPosition and camera position). * It iterated over the points with a step size on the line. * * @param viewport - Volume viewport * @param worldPos - World coordinates of the clicked location * @param targetVolumeId - target Volume ID in the viewport * @param criteriaFunction - A function that returns the point if it passes a certain * written logic, for instance, it can be a maxValue function that keeps the * records of all intensity values, and only return the point if its intensity * is greater than the maximum intensity of the points passed before. * @param stepsSize - Percentage of the spacing in the normal direction, default value * is 0.25 which means steps = 1/4 of the spacing in the normal direction. * @returns the World pos of the point that passes the criteriaFunction */ export default function getPointInLineOfSightWithCriteria( viewport: Types.IVolumeViewport, worldPos: Types.Point3, targetVolumeId: string, criteriaFunction: (intensity: number, point: Types.Point3) => Types.Point3, stepSize = 0.25 ): Types.Point3 { // 1. Getting the camera from the event details const camera = viewport.getCamera(); const { position: cameraPosition } = camera; // 2. Calculating the spacing in the normal direction, this will get // used as the step size for iterating over the points in the line of sight const { spacingInNormalDirection } = csUtils.getTargetVolumeAndSpacingInNormalDir( viewport, camera, targetVolumeId ); // 2.1 Making sure, we are not missing any point const step = spacingInNormalDirection * stepSize; // 3. Getting the bounds of the viewports. Search for brightest point is // limited to the visible bound // Todo: this might be a problem since bounds will change to spatial bounds. const bounds = viewport.getBounds(); const xMin = bounds[0]; const xMax = bounds[1]; // 5. Calculating the line, we use a parametric line definition const vector = <Types.Point3>[0, 0, 0]; // 5.1 Point coordinate on the line let point = <Types.Point3>[0, 0, 0]; // 5.2 Calculating the line direction, and storing in vector vtkMath.subtract(worldPos, cameraPosition, vector); let pickedPoint; // 6. Iterating over the line from the lower bound to the upper bound, with the // specified step size for (let pointT = xMin; pointT <= xMax; pointT = pointT + step) { // 6.1 Calculating the point x location point = [pointT, 0, 0]; // 6.2 Calculating the point y,z location based on the line equation const t = (pointT - cameraPosition[0]) / vector[0]; point[1] = t * vector[1] + cameraPosition[1]; point[2] = t * vector[2] + cameraPosition[2]; // 6.3 Checking if the points is inside the bounds if (_inBounds(point, bounds)) { // 6.4 Getting the intensity of the point const intensity = viewport.getIntensityFromWorld(point); // 6.5 Passing the intensity to the maximum value functions which decides // whether the current point is of interest based on some criteria const pointToPick = criteriaFunction(intensity, point); if (pointToPick) { pickedPoint = pointToPick; } } } return pickedPoint; } /** * Returns whether the point in the world is inside the bounds of the viewport * @param point - coordinates in the world * @returns boolean */ const _inBounds = function ( point: Types.Point3, bounds: Array<number> ): boolean { const [xMin, xMax, yMin, yMax, zMin, zMax] = bounds; return ( point[0] > xMin && point[0] < xMax && point[1] > yMin && point[1] < yMax && point[2] > zMin && point[2] < zMax ); }; |