ohif-viewer/Packages/ohif-viewerbase/client/lib/classes/StackImagePositionOffsetSynchronizer.js

216 lines
6.3 KiB
JavaScript
Raw Normal View History

import { Session } from 'meteor/session';
import { $ } from 'meteor/jquery';
2018-02-16 12:55:29 +01:00
import { OHIF } from 'meteor/ohif:core';
import { cornerstone, cornerstoneTools } from 'meteor/ohif:cornerstone';
import { toolManager } from '../toolManager';
export class StackImagePositionOffsetSynchronizer {
2017-02-09 00:10:01 +01:00
constructor() {
this.active = false;
this.syncedViewports = [];
this.synchronizer = new cornerstoneTools.Synchronizer('CornerstoneNewImage', cornerstoneTools.stackImagePositionOffsetSynchronizer);
}
2017-02-09 00:10:01 +01:00
static get ELEMENT_DISABLED_EVENT() {
2018-02-16 12:55:29 +01:00
return 'cornerstoneelementdisabled.StackImagePositionOffsetSynchronizer';
}
2017-02-09 00:10:01 +01:00
isActive() {
return this.active;
}
2017-02-09 00:10:01 +01:00
activate() {
const viewports = this.getLinkableViewports();
this.syncViewports(viewports);
}
2017-02-09 00:10:01 +01:00
activateByViewportIndexes(viewportIndexes) {
const viewports = this.getViewportByIndexes(viewportIndexes);
this.syncViewports(viewports);
}
2017-02-09 00:10:01 +01:00
deactivate() {
if (!this.isActive()) {
return;
}
while (this.syncedViewports.length) {
const viewport = this.syncedViewports[0];
this.removeViewport(viewport);
}
2017-02-09 00:10:01 +01:00
this.active = false;
toolManager.deactivateCommandButton('linkStackScroll');
}
2017-02-09 00:10:01 +01:00
update() {
if (!this.isActive()) {
return;
}
const activeViewportElement = this.getActiveViewportElement();
2017-02-09 00:10:01 +01:00
if (this.isViewportSynced(activeViewportElement)) {
return;
}
2017-02-09 00:10:01 +01:00
this.deactivate();
this.activate();
}
2017-02-09 00:10:01 +01:00
syncViewports(viewports) {
const viewportIndexes = [];
2017-02-09 00:10:01 +01:00
if (this.isActive() || (viewports.length <= 1)) {
return;
}
2017-02-09 00:10:01 +01:00
viewports.forEach((viewport, index) => {
this.synchronizer.add(viewport.element);
this.syncedViewports.push(viewport);
viewportIndexes.push(viewport.index);
2017-08-28 22:09:59 +02:00
2017-02-09 00:10:01 +01:00
$(viewport.element).on(StackImagePositionOffsetSynchronizer.ELEMENT_DISABLED_EVENT, this.elementDisabledHandler(this));
});
this.active = true;
toolManager.activateCommandButton('linkStackScroll');
Session.set('StackImagePositionOffsetSynchronizerLinkedViewports', viewportIndexes);
}
2017-02-09 00:10:01 +01:00
isViewportSynced(viewportElement) {
return !!this.getViewportByElement(viewportElement);
}
2017-02-09 00:10:01 +01:00
getActiveViewportElement() {
const viewportIndex = Session.get('activeViewport') || 0;
return $('.imageViewerViewport').get(viewportIndex);
}
2017-02-09 00:10:01 +01:00
removeViewport(viewport) {
const index = this.syncedViewports.indexOf(viewport);
2017-02-09 00:10:01 +01:00
if (index === -1) {
return;
}
2017-02-09 00:10:01 +01:00
this.syncedViewports.splice(index, 1);
this.synchronizer.remove(viewport.element);
this.removeLinkedViewportFromSession(viewport);
$(viewport.element).off(StackImagePositionOffsetSynchronizer.ELEMENT_DISABLED_EVENT);
}
2017-02-09 00:10:01 +01:00
getViewportByElement(viewportElement) {
const length = this.syncedViewports.length;
2017-02-09 00:10:01 +01:00
for (let i = 0; i < length; i++) {
const viewport = this.syncedViewports[i];
2017-08-28 22:09:59 +02:00
2017-02-09 00:10:01 +01:00
if (viewport.element === viewportElement) {
return viewport;
}
}
}
2017-02-09 00:10:01 +01:00
removeViewportByElement(viewportElement) {
let viewport = this.getViewportByElement(viewportElement);
2017-02-09 00:10:01 +01:00
if (viewport) {
this.removeViewport(viewport);
}
}
2017-02-09 00:10:01 +01:00
removeLinkedViewportFromSession(viewport) {
const linkedViewports = Session.get('StackImagePositionOffsetSynchronizerLinkedViewports');
const index = linkedViewports.indexOf(viewport.index);
2017-02-09 00:10:01 +01:00
if (index !== -1) {
linkedViewports.splice(index, 1);
Session.set('StackImagePositionOffsetSynchronizerLinkedViewports', linkedViewports);
}
}
2017-02-09 00:10:01 +01:00
elementDisabledHandler(context) {
return e => context.removeViewportByElement(e.detail.element);
}
2017-02-09 00:10:01 +01:00
getViewportByIndexes(viewportIndexes) {
const viewports = [];
const $viewportElements = $('.imageViewerViewport');
viewportIndexes.forEach(index => {
const element = $viewportElements.get(index);
2017-02-09 00:10:01 +01:00
if (!element) {
return;
}
2017-02-09 00:10:01 +01:00
viewports.push({
index,
element
});
});
return viewports;
}
2017-08-28 22:09:59 +02:00
isViewportsLinkable(viewportElementA, viewportElementB) {
const viewportAImageNormal = this.getViewportImageNormal(viewportElementA);
const viewportBImageNormal = this.getViewportImageNormal(viewportElementB);
if (viewportAImageNormal && viewportBImageNormal) {
const angleInRadians = viewportBImageNormal.angleTo(viewportAImageNormal);
// Pi / 12 radians = 15 degrees
// If the angle between two vectors is Pi, it means they are just inverted
return angleInRadians < Math.PI / 12 || angleInRadians === Math.PI;
}
return false;
}
2017-02-09 00:10:01 +01:00
getLinkableViewports() {
const activeViewportElement = this.getActiveViewportElement();
const viewports = [];
$('.imageViewerViewport').each((index, viewportElement) => {
2017-08-28 22:09:59 +02:00
if (this.isViewportsLinkable(activeViewportElement, viewportElement)) {
viewports.push({
index: index,
element: viewportElement
});
2017-02-09 00:10:01 +01:00
}
});
return viewports;
}
getViewportImageNormal(element) {
if (!element) {
return;
}
2017-02-09 00:10:01 +01:00
element = $(element).get(0);
2017-02-09 00:10:01 +01:00
try {
const enabledElement = cornerstone.getEnabledElement(element);
2017-02-09 00:10:01 +01:00
if (!enabledElement.image) {
return;
}
2017-02-09 00:10:01 +01:00
const imageId = enabledElement.image.imageId;
const imagePlane = cornerstone.metaData.get('imagePlane', imageId);
2017-02-09 00:10:01 +01:00
if (!imagePlane || !imagePlane.rowCosines || !imagePlane.columnCosines) {
return;
}
2017-02-09 00:10:01 +01:00
return imagePlane.rowCosines.clone().cross(imagePlane.columnCosines);
} catch(error) {
const errorMessage = error.message || error;
OHIF.log.info(`StackImagePositionOffsetSynchronizer getViewportImageNormal: ${errorMessage}`);
}
2017-02-09 00:10:01 +01:00
}
2018-02-16 12:55:29 +01:00
}