pre perviewport stacks

This commit is contained in:
Ross
2025-05-24 22:37:19 +01:00
parent 8d673fe28d
commit a803e351c3
2 changed files with 79 additions and 61 deletions
+66 -60
View File
@@ -1,5 +1,5 @@
import { useEffect, useRef, useCallback, useState } from "react" import { useEffect, useRef, useCallback, useState } from "react"
import createImageIds from "./lib/createImageIds.ts" import { createImageIds, availableImageIds } from "./lib/createImageIds.ts"
import { import {
RenderingEngine, RenderingEngine,
Enums, Enums,
@@ -251,48 +251,48 @@ function App() {
}; };
// Helper to apply all mouse tool bindings (normal or ctrl) // Helper to apply all mouse tool bindings (normal or ctrl)
const applyMouseToolBindings = useCallback(() => { const applyMouseToolBindings = useCallback(() => {
// Apply to both stack and volume tool groups // Apply to both stack and volume tool groups
const stackToolGroup = cornerstoneTools.ToolGroupManager.getToolGroup(STACK_TOOL_GROUP_ID); const stackToolGroup = cornerstoneTools.ToolGroupManager.getToolGroup(STACK_TOOL_GROUP_ID);
const volumeToolGroup = cornerstoneTools.ToolGroupManager.getToolGroup(VOLUME_TOOL_GROUP_ID); const volumeToolGroup = cornerstoneTools.ToolGroupManager.getToolGroup(VOLUME_TOOL_GROUP_ID);
[stackToolGroup, volumeToolGroup].forEach(toolGroup => { [stackToolGroup, volumeToolGroup].forEach(toolGroup => {
if (toolGroup) { if (toolGroup) {
// Set all tools to passive first, removing all bindings // Set all tools to passive first, removing all bindings
TOOL_OPTIONS.forEach(opt => { TOOL_OPTIONS.forEach(opt => {
toolGroup.setToolPassive(opt.value, { removeAllBindings: true }); toolGroup.setToolPassive(opt.value, { removeAllBindings: true });
}); });
// Collect all bindings for each tool // Collect all bindings for each tool
const toolBindings: Record<string, Array<any>> = {}; const toolBindings: Record<string, Array<any>> = {};
// Normal bindings // Normal bindings
Object.entries(mouseToolBindings).forEach(([btn, tool]) => { Object.entries(mouseToolBindings).forEach(([btn, tool]) => {
if (!toolBindings[tool]) toolBindings[tool] = []; if (!toolBindings[tool]) toolBindings[tool] = [];
toolBindings[tool].push({ mouseButton: MouseBindings[btn] }); toolBindings[tool].push({ mouseButton: MouseBindings[btn] });
}); });
// Ctrl bindings // Ctrl bindings
Object.entries(ctrlMouseToolBindings).forEach(([btn, tool]) => { Object.entries(ctrlMouseToolBindings).forEach(([btn, tool]) => {
if (!toolBindings[tool]) toolBindings[tool] = []; if (!toolBindings[tool]) toolBindings[tool] = [];
toolBindings[tool].push({ mouseButton: MouseBindings[btn], modifierKey: KeyboardBindings.Ctrl }); toolBindings[tool].push({ mouseButton: MouseBindings[btn], modifierKey: KeyboardBindings.Ctrl });
}); });
// Apply all bindings for each tool in a single call // Apply all bindings for each tool in a single call
Object.entries(toolBindings).forEach(([tool, bindings]) => { Object.entries(toolBindings).forEach(([tool, bindings]) => {
toolGroup.setToolActive(tool, { bindings }); toolGroup.setToolActive(tool, { bindings });
}); });
// Always re-apply the mouse wheel binding for StackScrollTool // Always re-apply the mouse wheel binding for StackScrollTool
toolGroup.setToolActive(StackScrollTool.toolName, { toolGroup.setToolActive(StackScrollTool.toolName, {
bindings: [ bindings: [
{ {
mouseButton: MouseBindings.Wheel, // Wheel Mouse mouseButton: MouseBindings.Wheel, // Wheel Mouse
}, },
], ],
}); });
} }
}); });
}, [mouseToolBindings, ctrlMouseToolBindings]); }, [mouseToolBindings, ctrlMouseToolBindings]);
const [sideMenuOpen, setSideMenuOpen] = useState(false); const [sideMenuOpen, setSideMenuOpen] = useState(false);
@@ -412,22 +412,6 @@ const applyMouseToolBindings = useCallback(() => {
.slice(0, viewportGrid.rows * viewportGrid.cols) .slice(0, viewportGrid.rows * viewportGrid.cols)
.filter(mode => mode === 'volume').length; .filter(mode => mode === 'volume').length;
// After the viewport setup loop, outside the for-loop:
if (
crossReferenceEnabled &&
visibleVolumeViewports >= 2
) {
if (!volumeToolGroup.hasTool(CrosshairsTool.toolName)) {
volumeToolGroup.addTool(CrosshairsTool.toolName);
}
volumeToolGroup.setToolEnabled(CrosshairsTool.toolName);
volumeToolGroup.setToolActive(CrosshairsTool.toolName, {
bindings: [{ mouseButton: MouseBindings.Primary }],
});
} else if (volumeToolGroup.hasTool(CrosshairsTool.toolName)) {
volumeToolGroup.setToolDisabled(CrosshairsTool.toolName);
}
// --- In your setup function, after tool group creation, enable/disable ReferenceLinesTool for each tool group --- // --- In your setup function, after tool group creation, enable/disable ReferenceLinesTool for each tool group ---
if (referenceLinesEnabled) { if (referenceLinesEnabled) {
if (!stackToolGroup.hasTool(ReferenceLinesTool.toolName)) { if (!stackToolGroup.hasTool(ReferenceLinesTool.toolName)) {
@@ -521,15 +505,13 @@ const applyMouseToolBindings = useCallback(() => {
}); });
} }
// Example: create and set a volume (you may need to adapt this for your data) // Use a unique volumeId per viewport
const volumeId = 'myVolumeId'; const volumeId = `myVolumeId_${i}`;
const volume = await volumeLoader.createAndCacheVolume(volumeId, { imageIds }); const volume = await volumeLoader.createAndCacheVolume(volumeId, { imageIds: sortedImageIds });
volume.load(); volume.load();
//await volumeLoader.loadVolume(volumeId);
viewport.setVolumes([{ volumeId }]); viewport.setVolumes([{ volumeId }]);
// Optionally restore properties for volume
viewport.render(); viewport.render();
return continue
} }
viewport.render(); viewport.render();
@@ -586,6 +568,30 @@ const applyMouseToolBindings = useCallback(() => {
updateOverlay(i, viewport); updateOverlay(i, viewport);
} }
const activeVolumeViewports = [];
for (let i = 0; i < viewportGrid.rows * viewportGrid.cols; i++) {
const viewportId = `CT_${i}`;
const viewport = renderingEngineRef.current?.getViewport(viewportId);
if (viewport && viewportModes[i] === 'volume') {
activeVolumeViewports.push(viewport);
}
}
if (
crossReferenceEnabled &&
activeVolumeViewports.length >= 2
) {
if (!volumeToolGroup.hasTool(CrosshairsTool.toolName)) {
volumeToolGroup.addTool(CrosshairsTool.toolName);
}
volumeToolGroup.setToolEnabled(CrosshairsTool.toolName);
volumeToolGroup.setToolActive(CrosshairsTool.toolName, {
bindings: [{ mouseButton: MouseBindings.Primary }],
});
} else if (volumeToolGroup.hasTool(CrosshairsTool.toolName)) {
volumeToolGroup.setToolDisabled(CrosshairsTool.toolName);
}
// 7. Apply mouse tool bindings // 7. Apply mouse tool bindings
applyMouseToolBindings(); applyMouseToolBindings();
}; };
+13 -1
View File
@@ -65,7 +65,7 @@ import { readFile } from "dicom-parser"
const NUM_IMAGES = 15 // set to however many images you have const NUM_IMAGES = 15 // set to however many images you have
export default async function createImageIds() { export async function createImageIds() {
const imageIds = [] const imageIds = []
for (let i = 1; i <= NUM_IMAGES; i++) { for (let i = 1; i <= NUM_IMAGES; i++) {
const fileName = `IMG${String(i)}.dcm` const fileName = `IMG${String(i)}.dcm`
@@ -73,3 +73,15 @@ export default async function createImageIds() {
} }
return imageIds return imageIds
} }
export async function availableImageIds() {
// Example: two stacks, each with 10 images
const stacks = [
Array.from({ length: 15 }, (_, i) => `wadouri:/test_images/stack2/IMG${i + 1}.dcm`),
Array.from({ length: 25 }, (_, i) => `wadouri:/test_images/stack5/IMG${i + 1}.dcm`),
Array.from({ length: 26 }, (_, i) => `wadouri:/test_images/stack3/IMG${i + 1}.dcm`),
// Add more stacks as needed
];
return stacks;
}