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 106 107 108 109 110 111 112 113 114 115 116 117 118 | import { vec3 } from 'gl-matrix'; import type { Types } from '@cornerstonejs/core'; import type { InitializedOperationData } from '../BrushStrategy'; import type BoundsIJK from '../../../../types/BoundsIJK'; import StrategyCallbacks from '../../../../enums/StrategyCallbacks'; /** * Initializes the threshold values for the dynamic threshold. * If the threshold is undefined/null, the threshold will be set * by looking at the area centered on the centerIJK, with a delta radius, * and taking the range of those pixel values. * If the threshold is already set, then the range will be extended by just the * center voxel at centerIJK. */ export default { [StrategyCallbacks.Initialize]: (operationData: InitializedOperationData) => { const { operationName, centerIJK, strategySpecificConfiguration, segmentationVoxelManager: segmentationVoxelManager, imageVoxelManager: imageVoxelManager, segmentIndex, } = operationData; const { THRESHOLD } = strategySpecificConfiguration; if (!THRESHOLD?.isDynamic || !centerIJK || !segmentIndex) { return; } if ( operationName === StrategyCallbacks.RejectPreview || operationName === StrategyCallbacks.OnInteractionEnd ) { return; } const { boundsIJK } = segmentationVoxelManager; const { threshold: oldThreshold, dynamicRadius = 0 } = THRESHOLD; const useDelta = oldThreshold ? 0 : dynamicRadius; const nestedBounds = boundsIJK.map((ijk, idx) => { const [min, max] = ijk; return [ Math.max(min, centerIJK[idx] - useDelta), Math.min(max, centerIJK[idx] + useDelta), ]; }) as BoundsIJK; const threshold = oldThreshold || [Infinity, -Infinity]; // TODO - threshold on all three values separately const callback = ({ value }) => { const gray = Array.isArray(value) ? vec3.len(value as any) : value; threshold[0] = Math.min(gray, threshold[0]); threshold[1] = Math.max(gray, threshold[1]); }; imageVoxelManager.forEach(callback, { boundsIJK: nestedBounds }); operationData.strategySpecificConfiguration.THRESHOLD.threshold = threshold; }, // Setup a clear threshold value on mouse/touch down [StrategyCallbacks.OnInteractionStart]: ( operationData: InitializedOperationData ) => { const { strategySpecificConfiguration, preview } = operationData; if (!strategySpecificConfiguration?.THRESHOLD?.isDynamic && !preview) { return; } strategySpecificConfiguration.THRESHOLD.threshold = null; }, /** * It computes the inner circle radius in canvas coordinates and stores it * in the strategySpecificConfiguration. This is used to show the user * the area that is used to compute the threshold. */ [StrategyCallbacks.ComputeInnerCircleRadius]: ( operationData: InitializedOperationData ) => { const { configuration, viewport } = operationData; const { THRESHOLD: { dynamicRadius = 0 } = {} } = configuration.strategySpecificConfiguration || {}; if (dynamicRadius === 0) { return; } const { spacing } = ( viewport as Types.IStackViewport | Types.IVolumeViewport ).getImageData(); const centerCanvas = [ viewport.element.clientWidth / 2, viewport.element.clientHeight / 2, ] as Types.Point2; const radiusInWorld = dynamicRadius * spacing[0]; const centerCursorInWorld = viewport.canvasToWorld(centerCanvas); const offSetCenterInWorld = centerCursorInWorld.map( (coord) => coord + radiusInWorld ) as Types.Point3; const offSetCenterCanvas = viewport.worldToCanvas(offSetCenterInWorld); const dynamicRadiusInCanvas = Math.abs( centerCanvas[0] - offSetCenterCanvas[0] ); // this is a bit of a hack, since we have switched to using THRESHOLD // as strategy but really strategy names are CIRCLE_THRESHOLD and SPHERE_THRESHOLD // and we can't really change the name of the strategy in the configuration const { strategySpecificConfiguration, activeStrategy } = configuration; if (!strategySpecificConfiguration[activeStrategy]) { strategySpecificConfiguration[activeStrategy] = {}; } strategySpecificConfiguration[activeStrategy].dynamicRadiusInCanvas = dynamicRadiusInCanvas; }, }; |