Anonymous
Как программно добавить и провести измерения из макетных данных в Ohif/Cornerstone.js? [закрыто]
Сообщение
Anonymous » 18 июн 2025, 14:49
Я работаю над проектом, основанным на зрителе Ohif. Моя цель состоит в том, чтобы загрузить данные измерения из макетного файла JSON и автоматически нарисовать его на соответствующий срез изображения, когда зритель загружается. Внутри этого крюка я делаю следующее: < /p>
Прочитайте мои данные о измерении. Показывает данные правильно. Тем не менее, аннотация (фактический рисунок PlanarFreeHandroi) не отображается на слое SVG ViewPort. В консоли нет ошибок. SeasurementService.AnnotationTomeasurement и AnnotationManager.Addannotation вручную. Это правильным, или MeasureMerservice.AddMeasurement автоматически обрабатывает рендеринг через его отображения?
В моей текущей реализации используется крюк использования. Есть ли более надежный подход на основе событий (например, прослушивание enums.events.image_rendered), чтобы убедиться, что просмотр будет полностью готов, прежде чем я попытаюсь добавить аннотацию?
Вот соответствующие фрагменты кода и моя макетная структура данных. Любое руководство было бы очень оценено! < /P>
Код: Выделить всё
const getViewportInfo = useCallback(() => {
return cornerstoneViewportService.getViewportInfo(activeViewportId);
}, [cornerstoneViewportService, activeViewportId]);
const getCurrentImageId = useCallback(() => {
if (!activeViewportId) return null;
const viewportObj = cornerstoneViewportService.getCornerstoneViewport(activeViewportId);
return viewportObj?.getCurrentImageId();
}, [cornerstoneViewportService, activeViewportId]);
if (!dataSource) {
console.error('ViewerLayout: Invalid DataSource');
} else {
servicesManager.services.dataSource = dataSource;
servicesManager.services.getImageIdsForDisplaySet = ds =>
dataSource.getImageIdsForDisplaySet(ds);
}
const customToMeasurementSchema = useCallback(
raw => {
console.log('customToMeasurementSchema', raw);
if (!dataSource?.getImageIdsForDisplaySet || !displaySetService.getDisplaySetByUID) {
return null;
}
const ds = displaySetService.getDisplaySetByUID(raw.displaySetInstanceUID);
if (!ds) {
console.warn(`DisplaySet with UID ${raw.displaySetInstanceUID} not found.`);
return null;
}
const imageIds = dataSource.getImageIdsForDisplaySet(ds) || [];
const imageId = imageIds[raw.frameNumber - 1] || imageIds[0];
const measurementSchema = {
uid: raw.uid,
SOPInstanceUID: raw.SOPInstanceUID,
FrameOfReferenceUID: ds.FrameOfReferenceUID || raw.metadata?.FrameOfReferenceUID,
referenceStudyUID: raw.referenceStudyUID || raw.studyInstanceUID,
referenceSeriesUID: raw.seriesInstanceUID || ds.SeriesInstanceUID,
frameNumber: raw.frameNumber || 1,
displaySetInstanceUID: raw.displaySetInstanceUID,
label: raw.label || '',
displayText: raw.displayText || [],
type: raw.type,
points: raw.points || [],
source: raw.source,
toolName: raw.toolName,
referencedImageId: imageId,
metadata: {
...raw.metadata,
FrameOfReferenceUID: ds.FrameOfReferenceUID || raw.metadata?.FrameOfReferenceUID,
referencedImageId: imageId,
},
data: { [imageId]: raw.data },
selected: raw.selected || false,
textBox: raw.textBox,
};
console.log('customToMeasurementSchema Output:', measurementSchema);
return measurementSchema;
},
[dataSource, displaySetService]
);
const toAnnotationSchema = useCallback((measurement, annotationType) => {
const annotationObj = {
annotationType,
uid: measurement.uid,
imageId: measurement.referencedImageId,
frameNumber: measurement.frameNumber || 1,
visible: true,
handles: {
points: measurement.points.map(([x, y, z]) => ({
x,
y,
world: [x, y, z],
})),
textBox: {
x: measurement.textBox?.worldPosition[0],
y: measurement.textBox?.worldPosition[1],
},
},
textBox: {
x: measurement.textBox?.worldPosition[0],
y: measurement.textBox?.worldPosition[1],
},
style: {
color: 'rgb(0,255,0)',
lineWidth: 3.5,
fill: 'rgba(0,255,0,0.1)',
},
metadata: {
...(measurement.metadata || {}),
FrameOfReferenceUID:
measurement.metadata?.FrameOfReferenceUID || measurement.FrameOfReferenceUID || '',
},
data: measurement.data,
};
console.log('toAnnotationSchema Output:', annotationObj);
return annotationObj;
}, []);
const injectMeasurements = useCallback(
(currentImageId, displayUID, instance, viewportElement) => {
console.log('Instance object in injectMeasurements:', instance);
const renderingEngine = getRenderingEngine(renderingEngineId);
if (!renderingEngine) {
console.error('Rendering engine not found in injectMeasurements');
return;
}
const viewport = renderingEngine.getViewport(activeViewportId);
if (!viewport) {
console.error('Viewport not found');
return;
}
const { clientWidth, clientHeight } = viewport.element;
const topLeftWorld = viewport.canvasToWorld([0, 0]);
const bottomRightWorld = viewport.canvasToWorld([clientWidth, clientHeight]);
const center = [
(topLeftWorld[0] + bottomRightWorld[0]) / 2,
(topLeftWorld[1] + bottomRightWorld[1]) / 2,
(topLeftWorld[2] + bottomRightWorld[2]) / 2,
];
const worldWidth = Math.abs(bottomRightWorld[0] - topLeftWorld[0]);
const worldHeight = Math.abs(bottomRightWorld[1] - topLeftWorld[1]);
const dynamicPoints = [
[center[0] - worldWidth * 0.1, center[1] - worldHeight * 0.1, center[2]],
[center[0] + worldWidth * 0.1, center[1] - worldHeight * 0.1, center[2]],
[center[0] + worldWidth * 0.1, center[1] + worldHeight * 0.1, center[2]],
[center[0] - worldWidth * 0.1, center[1] + worldHeight * 0.1, center[2]],
];
console.log('Calculated dynamic points:', dynamicPoints);
const commonProps = {
displaySetInstanceUID: displayUID,
StudyInstanceUID: instance.StudyInstanceUID,
referenceStudyUID: instance.StudyInstanceUID,
referenceSeriesUID: instance.SeriesInstanceUID,
SOPInstanceUID: instance.SOPInstanceUID,
metadata: {
...measurementsMock[0],
FrameOfReferenceUID: instance.FrameOfReferenceUID,
referencedImageId: currentImageId,
data: measurementsMock[0].data,
textBox: measurementsMock[0].textBox,
},
FrameOfReferenceUID: instance.FrameOfReferenceUID,
};
console.log('Common Props before raw assignment (with actual UIDs):', commonProps);
const source = measurementService.getSource('Cornerstone3DTools', '0.1');
const annotationManager = annotation.state.getAnnotationManager();
if (!annotationManager || typeof annotationManager.addAnnotation !== 'function') {
console.error(
'Annotation Manager is not available or addAnnotation method is missing! Cannot inject measurements.'
);
return;
}
const rawTemplate = measurementsMock[0];
measurementsMock.forEach(rawTemplate => {
const raw = {
...rawTemplate,
...commonProps,
points: dynamicPoints,
metadata: {
...(rawTemplate.metadata || {}),
...(commonProps.metadata || {}),
},
referencedImageId: currentImageId,
SOPInstanceUID: commonProps.SOPInstanceUID,
FrameOfReferenceUID: commonProps.FrameOfReferenceUID,
referenceSeriesUID: commonProps.referenceSeriesUID,
referenceStudyUID: commonProps.referenceStudyUID,
};
console.log('Raw object for customToMeasurementSchema (after dynamic merge):', raw);
measurementService.annotationToMeasurement(
source,
measurementService.VALUE_TYPES.POLYLINE,
raw,
false
);
let existingAnnotation = annotationManager.getAnnotation(raw.uid);
if (!existingAnnotation) {
console.log('Injecting measurement (no existing annotation found with this UID)');
const annotationObj = toAnnotationSchema(raw, raw.toolName || 'PlanarFreehandROI');
console.log('Eklenecek Annotation FoR:', annotationObj.metadata.FrameOfReferenceUID);
annotationObj.imageId = currentImageId;
console.log(
'Final annotationObj before addAnnotation (full object):',
JSON.stringify(annotationObj, null, 2)
);
const engine = getRenderingEngine(renderingEngineId);
if (!engine) {
console.error(`[ViewerLayout] Geçersiz renderingEngineId: ${renderingEngineId}`);
return;
}
const groupKey = annotationObj.metadata.FrameOfReferenceUID;
annotationManager.addAnnotation(annotationObj, groupKey);
engine.render();
const added = annotationManager.getAnnotation(raw.uid);
if (!added) {
console.error(`Annotation UID ${raw.uid} eklenemedi.`);
}
console.log(
'Annotation retrieved from manager AFTER addAnnotation:',
annotationManager.getAnnotation(raw.uid)
);
} else {
console.log(
`Annotation with UID ${raw.uid} already exists in manager. Skipping injection.`
);
}
});
},
[measurementService, toAnnotationSchema, renderingEngineId, activeViewportId]
);
useEffect(() => {
const source = measurementService.getSource('Cornerstone3DTools', '0.1');
measurementService.addMapping(
source,
measurementService.VALUE_TYPES.POLYLINE,
{ points: measurementsMock[0].points.length },
toAnnotationSchema,
customToMeasurementSchema
);
}, [measurementService, toAnnotationSchema, customToMeasurementSchema]);
useEffect(() => {
const timeoutId = setTimeout(() => {
const viewportInfo = getViewportInfo();
if (viewportInfo?.renderingEngineId) {
setRenderingEngineId(viewportInfo.renderingEngineId);
console.log('[ViewerLayout] renderingEngineId set:', viewportInfo.renderingEngineId);
}
}, 5000);
return () => clearTimeout(timeoutId);
}, [getViewportInfo]);
useEffect(() => {
if (!renderingEngineId || !activeViewportId) return;
const toolGroup = ToolGroupManager.getToolGroupForViewport(activeViewportId, renderingEngineId);
if (!toolGroup) {
console.error('ToolGroup not available, skipping tool configuration.');
return;
}
toolGroup.setToolActive(PlanarFreehandROITool.toolName, {
bindings: [{ mouseButton: Enums.MouseBindings.Primary }],
});
console.log('[ViewerLayout] Tool configured for:', toolGroup);
}, [renderingEngineId, activeViewportId]);
useEffect(() => {
if (!activeViewportId || !viewports.has(activeViewportId) || !renderingEngineId) {
return;
}
const renderingEngine = getRenderingEngine(renderingEngineId);
if (!renderingEngine) {
console.error('ViewerLayout: Invalid Rendering Engine');
return;
}
const viewport = renderingEngine.getViewport(activeViewportId);
if (!viewport) {
console.error('ViewerLayout: Invalid Viewport');
return;
}
const currentImageId = getCurrentImageId();
console.log('Active Viewport currentImageId:', currentImageId);
if (!currentImageId) {
console.error('ViewerLayout: No current image ID');
return;
}
if (showLoadingIndicator) {
setShowLoadingIndicator(false);
}
const dsUIDs = viewports.get(activeViewportId).displaySetInstanceUIDs || [];
if (!dsUIDs.length) return;
const displayUID = dsUIDs[0];
const ds = displaySetService.getDisplaySetByUID(displayUID);
if (!ds?.instances?.length) return;
const instance = ds.instances[0];
const toolGroup = ToolGroupManager.getToolGroupForViewport(activeViewportId, renderingEngineId);
if (toolGroup) {
const viewportIdsInToolGroup = toolGroup.getViewportIds();
console.log('Viewport IDs in ToolGroup:', viewportIdsInToolGroup);
let isViewportAlreadyAdded = false;
if (Array.isArray(viewportIdsInToolGroup)) {
isViewportAlreadyAdded = viewportIdsInToolGroup.includes(activeViewportId);
}
if (!isViewportAlreadyAdded) {
toolGroup.addViewport(activeViewportId, renderingEngineId);
console.log(
`[ViewerLayout] Added viewport ${activeViewportId} (engine: ${renderingEngineId}) to toolGroup ${toolGroup.id}`
);
}
} else {
console.error(`No toolGroup found for viewport ${activeViewportId}. Cannot add viewport.`);
return;
}
injectMeasurements(currentImageId, displayUID, instance, viewport.element);
viewport.render();
console.log('[ViewerLayout] Measurements and annotations injected successfully');
}, [
activeViewportId,
viewports,
renderingEngineId,
displaySetService,
getCurrentImageId,
injectMeasurements,
showLoadingIndicator,
]);
максимальные данные добавляются в службу измерения, служба аннотаций также запускается, и, по -видимому, добавлены данные, но соответствующие изменения не отображаются на слое SVG, в результате, рисунок не видно на изображении.
Подробнее здесь:
https://stackoverflow.com/questions/796 ... if-corners
1750247352
Anonymous
Я работаю над проектом, основанным на зрителе Ohif. Моя цель состоит в том, чтобы загрузить данные измерения из макетного файла JSON и автоматически нарисовать его на соответствующий срез изображения, когда зритель загружается. Внутри этого крюка я делаю следующее: < /p> Прочитайте мои данные о измерении. Показывает данные правильно. Тем не менее, аннотация (фактический рисунок PlanarFreeHandroi) не отображается на слое SVG ViewPort. В консоли нет ошибок. SeasurementService.AnnotationTomeasurement и AnnotationManager.Addannotation вручную. Это правильным, или MeasureMerservice.AddMeasurement автоматически обрабатывает рендеринг через его отображения? В моей текущей реализации используется крюк использования. Есть ли более надежный подход на основе событий (например, прослушивание enums.events.image_rendered), чтобы убедиться, что просмотр будет полностью готов, прежде чем я попытаюсь добавить аннотацию? Вот соответствующие фрагменты кода и моя макетная структура данных. Любое руководство было бы очень оценено! < /P> [code] const getViewportInfo = useCallback(() => { return cornerstoneViewportService.getViewportInfo(activeViewportId); }, [cornerstoneViewportService, activeViewportId]); const getCurrentImageId = useCallback(() => { if (!activeViewportId) return null; const viewportObj = cornerstoneViewportService.getCornerstoneViewport(activeViewportId); return viewportObj?.getCurrentImageId(); }, [cornerstoneViewportService, activeViewportId]); if (!dataSource) { console.error('ViewerLayout: Invalid DataSource'); } else { servicesManager.services.dataSource = dataSource; servicesManager.services.getImageIdsForDisplaySet = ds => dataSource.getImageIdsForDisplaySet(ds); } const customToMeasurementSchema = useCallback( raw => { console.log('customToMeasurementSchema', raw); if (!dataSource?.getImageIdsForDisplaySet || !displaySetService.getDisplaySetByUID) { return null; } const ds = displaySetService.getDisplaySetByUID(raw.displaySetInstanceUID); if (!ds) { console.warn(`DisplaySet with UID ${raw.displaySetInstanceUID} not found.`); return null; } const imageIds = dataSource.getImageIdsForDisplaySet(ds) || []; const imageId = imageIds[raw.frameNumber - 1] || imageIds[0]; const measurementSchema = { uid: raw.uid, SOPInstanceUID: raw.SOPInstanceUID, FrameOfReferenceUID: ds.FrameOfReferenceUID || raw.metadata?.FrameOfReferenceUID, referenceStudyUID: raw.referenceStudyUID || raw.studyInstanceUID, referenceSeriesUID: raw.seriesInstanceUID || ds.SeriesInstanceUID, frameNumber: raw.frameNumber || 1, displaySetInstanceUID: raw.displaySetInstanceUID, label: raw.label || '', displayText: raw.displayText || [], type: raw.type, points: raw.points || [], source: raw.source, toolName: raw.toolName, referencedImageId: imageId, metadata: { ...raw.metadata, FrameOfReferenceUID: ds.FrameOfReferenceUID || raw.metadata?.FrameOfReferenceUID, referencedImageId: imageId, }, data: { [imageId]: raw.data }, selected: raw.selected || false, textBox: raw.textBox, }; console.log('customToMeasurementSchema Output:', measurementSchema); return measurementSchema; }, [dataSource, displaySetService] ); const toAnnotationSchema = useCallback((measurement, annotationType) => { const annotationObj = { annotationType, uid: measurement.uid, imageId: measurement.referencedImageId, frameNumber: measurement.frameNumber || 1, visible: true, handles: { points: measurement.points.map(([x, y, z]) => ({ x, y, world: [x, y, z], })), textBox: { x: measurement.textBox?.worldPosition[0], y: measurement.textBox?.worldPosition[1], }, }, textBox: { x: measurement.textBox?.worldPosition[0], y: measurement.textBox?.worldPosition[1], }, style: { color: 'rgb(0,255,0)', lineWidth: 3.5, fill: 'rgba(0,255,0,0.1)', }, metadata: { ...(measurement.metadata || {}), FrameOfReferenceUID: measurement.metadata?.FrameOfReferenceUID || measurement.FrameOfReferenceUID || '', }, data: measurement.data, }; console.log('toAnnotationSchema Output:', annotationObj); return annotationObj; }, []); const injectMeasurements = useCallback( (currentImageId, displayUID, instance, viewportElement) => { console.log('Instance object in injectMeasurements:', instance); const renderingEngine = getRenderingEngine(renderingEngineId); if (!renderingEngine) { console.error('Rendering engine not found in injectMeasurements'); return; } const viewport = renderingEngine.getViewport(activeViewportId); if (!viewport) { console.error('Viewport not found'); return; } const { clientWidth, clientHeight } = viewport.element; const topLeftWorld = viewport.canvasToWorld([0, 0]); const bottomRightWorld = viewport.canvasToWorld([clientWidth, clientHeight]); const center = [ (topLeftWorld[0] + bottomRightWorld[0]) / 2, (topLeftWorld[1] + bottomRightWorld[1]) / 2, (topLeftWorld[2] + bottomRightWorld[2]) / 2, ]; const worldWidth = Math.abs(bottomRightWorld[0] - topLeftWorld[0]); const worldHeight = Math.abs(bottomRightWorld[1] - topLeftWorld[1]); const dynamicPoints = [ [center[0] - worldWidth * 0.1, center[1] - worldHeight * 0.1, center[2]], [center[0] + worldWidth * 0.1, center[1] - worldHeight * 0.1, center[2]], [center[0] + worldWidth * 0.1, center[1] + worldHeight * 0.1, center[2]], [center[0] - worldWidth * 0.1, center[1] + worldHeight * 0.1, center[2]], ]; console.log('Calculated dynamic points:', dynamicPoints); const commonProps = { displaySetInstanceUID: displayUID, StudyInstanceUID: instance.StudyInstanceUID, referenceStudyUID: instance.StudyInstanceUID, referenceSeriesUID: instance.SeriesInstanceUID, SOPInstanceUID: instance.SOPInstanceUID, metadata: { ...measurementsMock[0], FrameOfReferenceUID: instance.FrameOfReferenceUID, referencedImageId: currentImageId, data: measurementsMock[0].data, textBox: measurementsMock[0].textBox, }, FrameOfReferenceUID: instance.FrameOfReferenceUID, }; console.log('Common Props before raw assignment (with actual UIDs):', commonProps); const source = measurementService.getSource('Cornerstone3DTools', '0.1'); const annotationManager = annotation.state.getAnnotationManager(); if (!annotationManager || typeof annotationManager.addAnnotation !== 'function') { console.error( 'Annotation Manager is not available or addAnnotation method is missing! Cannot inject measurements.' ); return; } const rawTemplate = measurementsMock[0]; measurementsMock.forEach(rawTemplate => { const raw = { ...rawTemplate, ...commonProps, points: dynamicPoints, metadata: { ...(rawTemplate.metadata || {}), ...(commonProps.metadata || {}), }, referencedImageId: currentImageId, SOPInstanceUID: commonProps.SOPInstanceUID, FrameOfReferenceUID: commonProps.FrameOfReferenceUID, referenceSeriesUID: commonProps.referenceSeriesUID, referenceStudyUID: commonProps.referenceStudyUID, }; console.log('Raw object for customToMeasurementSchema (after dynamic merge):', raw); measurementService.annotationToMeasurement( source, measurementService.VALUE_TYPES.POLYLINE, raw, false ); let existingAnnotation = annotationManager.getAnnotation(raw.uid); if (!existingAnnotation) { console.log('Injecting measurement (no existing annotation found with this UID)'); const annotationObj = toAnnotationSchema(raw, raw.toolName || 'PlanarFreehandROI'); console.log('Eklenecek Annotation FoR:', annotationObj.metadata.FrameOfReferenceUID); annotationObj.imageId = currentImageId; console.log( 'Final annotationObj before addAnnotation (full object):', JSON.stringify(annotationObj, null, 2) ); const engine = getRenderingEngine(renderingEngineId); if (!engine) { console.error(`[ViewerLayout] Geçersiz renderingEngineId: ${renderingEngineId}`); return; } const groupKey = annotationObj.metadata.FrameOfReferenceUID; annotationManager.addAnnotation(annotationObj, groupKey); engine.render(); const added = annotationManager.getAnnotation(raw.uid); if (!added) { console.error(`Annotation UID ${raw.uid} eklenemedi.`); } console.log( 'Annotation retrieved from manager AFTER addAnnotation:', annotationManager.getAnnotation(raw.uid) ); } else { console.log( `Annotation with UID ${raw.uid} already exists in manager. Skipping injection.` ); } }); }, [measurementService, toAnnotationSchema, renderingEngineId, activeViewportId] ); useEffect(() => { const source = measurementService.getSource('Cornerstone3DTools', '0.1'); measurementService.addMapping( source, measurementService.VALUE_TYPES.POLYLINE, { points: measurementsMock[0].points.length }, toAnnotationSchema, customToMeasurementSchema ); }, [measurementService, toAnnotationSchema, customToMeasurementSchema]); useEffect(() => { const timeoutId = setTimeout(() => { const viewportInfo = getViewportInfo(); if (viewportInfo?.renderingEngineId) { setRenderingEngineId(viewportInfo.renderingEngineId); console.log('[ViewerLayout] renderingEngineId set:', viewportInfo.renderingEngineId); } }, 5000); return () => clearTimeout(timeoutId); }, [getViewportInfo]); useEffect(() => { if (!renderingEngineId || !activeViewportId) return; const toolGroup = ToolGroupManager.getToolGroupForViewport(activeViewportId, renderingEngineId); if (!toolGroup) { console.error('ToolGroup not available, skipping tool configuration.'); return; } toolGroup.setToolActive(PlanarFreehandROITool.toolName, { bindings: [{ mouseButton: Enums.MouseBindings.Primary }], }); console.log('[ViewerLayout] Tool configured for:', toolGroup); }, [renderingEngineId, activeViewportId]); useEffect(() => { if (!activeViewportId || !viewports.has(activeViewportId) || !renderingEngineId) { return; } const renderingEngine = getRenderingEngine(renderingEngineId); if (!renderingEngine) { console.error('ViewerLayout: Invalid Rendering Engine'); return; } const viewport = renderingEngine.getViewport(activeViewportId); if (!viewport) { console.error('ViewerLayout: Invalid Viewport'); return; } const currentImageId = getCurrentImageId(); console.log('Active Viewport currentImageId:', currentImageId); if (!currentImageId) { console.error('ViewerLayout: No current image ID'); return; } if (showLoadingIndicator) { setShowLoadingIndicator(false); } const dsUIDs = viewports.get(activeViewportId).displaySetInstanceUIDs || []; if (!dsUIDs.length) return; const displayUID = dsUIDs[0]; const ds = displaySetService.getDisplaySetByUID(displayUID); if (!ds?.instances?.length) return; const instance = ds.instances[0]; const toolGroup = ToolGroupManager.getToolGroupForViewport(activeViewportId, renderingEngineId); if (toolGroup) { const viewportIdsInToolGroup = toolGroup.getViewportIds(); console.log('Viewport IDs in ToolGroup:', viewportIdsInToolGroup); let isViewportAlreadyAdded = false; if (Array.isArray(viewportIdsInToolGroup)) { isViewportAlreadyAdded = viewportIdsInToolGroup.includes(activeViewportId); } if (!isViewportAlreadyAdded) { toolGroup.addViewport(activeViewportId, renderingEngineId); console.log( `[ViewerLayout] Added viewport ${activeViewportId} (engine: ${renderingEngineId}) to toolGroup ${toolGroup.id}` ); } } else { console.error(`No toolGroup found for viewport ${activeViewportId}. Cannot add viewport.`); return; } injectMeasurements(currentImageId, displayUID, instance, viewport.element); viewport.render(); console.log('[ViewerLayout] Measurements and annotations injected successfully'); }, [ activeViewportId, viewports, renderingEngineId, displaySetService, getCurrentImageId, injectMeasurements, showLoadingIndicator, ]); [/code] максимальные данные добавляются в службу измерения, служба аннотаций также запускается, и, по -видимому, добавлены данные, но соответствующие изменения не отображаются на слое SVG, в результате, рисунок не видно на изображении. Подробнее здесь: [url]https://stackoverflow.com/questions/79670468/how-to-programmatically-add-and-draw-measurements-from-mock-data-in-ohif-corners[/url]