Skip to content

Commit

Permalink
fix: annotation rendering engine on viewport removal (#303)
Browse files Browse the repository at this point in the history
* feat: add hasBeenDestroyed to viewport and fix bugs

* fix: reset annotation render on remove element

* new api

* apply review comments
  • Loading branch information
sedghi committed Nov 21, 2022
1 parent ef62817 commit aeb205e
Show file tree
Hide file tree
Showing 11 changed files with 70 additions and 5 deletions.
4 changes: 4 additions & 0 deletions common/reviews/api/core.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -1279,6 +1279,8 @@ interface IViewport {
// (undocumented)
id: string;
// (undocumented)
isDisabled: boolean;
// (undocumented)
options: ViewportInputOptions;
// (undocumented)
removeAllActors(): void;
Expand Down Expand Up @@ -2042,6 +2044,8 @@ export class Viewport implements IViewport {
// (undocumented)
protected initialCamera: ICamera;
// (undocumented)
isDisabled: boolean;
// (undocumented)
_isInBounds(point: Point3, bounds: number[]): boolean;
// (undocumented)
options: ViewportInputOptions;
Expand Down
1 change: 1 addition & 0 deletions common/reviews/api/streaming-image-volume-loader.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -905,6 +905,7 @@ interface IViewport {
getRenderingEngine(): any;
getZoom(): number;
id: string;
isDisabled: boolean;
options: ViewportInputOptions;
removeAllActors(): void;
render(): void;
Expand Down
1 change: 1 addition & 0 deletions common/reviews/api/tools.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -2456,6 +2456,7 @@ interface IViewport {
getRenderingEngine(): any;
getZoom(): number;
id: string;
isDisabled: boolean;
options: ViewportInputOptions;
removeAllActors(): void;
render(): void;
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/RenderingEngine/RenderingEngine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,7 @@ class RenderingEngine implements IRenderingEngine {

// 5. Remove the requested viewport from the rendering engine
this._removeViewport(viewportId);
viewport.isDisabled = true;

// 6. Avoid rendering for the disabled viewport
this._needsRender.delete(viewportId);
Expand Down
2 changes: 2 additions & 0 deletions packages/core/src/RenderingEngine/Viewport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ class Viewport implements IViewport {
protected flipHorizontal = false;
protected flipVertical = false;
protected rotation = 0;
public isDisabled: boolean;

/** sx of viewport on the offscreen canvas */
sx: number;
Expand Down Expand Up @@ -95,6 +96,7 @@ class Viewport implements IViewport {
? props.defaultOptions.suppressEvents
: false;
this.options = _cloneDeep(props.defaultOptions);
this.isDisabled = false;
}

getFrameOfReferenceUID: () => string;
Expand Down
6 changes: 6 additions & 0 deletions packages/core/src/RenderingEngine/VolumeViewport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,12 @@ class VolumeViewport extends Viewport implements IVolumeViewport {
const volumeNewImageCleanUpBound = volumeNewImageCleanUp.bind(this);

function volumeNewImageHandler(cameraEvent) {
const { viewportId } = cameraEvent.detail;

if (viewportId !== this.id || this.isDisabled) {
return;
}

const viewportImageData = this.getImageData();

if (!viewportImageData) {
Expand Down
2 changes: 2 additions & 0 deletions packages/core/src/types/IViewport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ interface IViewport {
options: ViewportInputOptions;
/** Suppress events */
suppressEvents: boolean;
/** if the viewport has been disabled */
isDisabled: boolean;
/** frameOfReferenceUID the viewport's default actor is rendering */
getFrameOfReferenceUID: () => string;
/** method to convert canvas to world coordinates */
Expand Down
27 changes: 27 additions & 0 deletions packages/tools/src/tools/CrosshairsTool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,33 @@ class CrosshairsTool extends AnnotationTool {
const viewportsInfo = this._getViewportsInfo();

this._unsubscribeToViewportNewVolumeSet(viewportsInfo);

// Crosshairs annotations in the state
// has no value when the tool is disabled
// since viewports can change (zoom, pan, scroll)
// between disabled and enabled/active states.
// so we just remove the annotations from the state
viewportsInfo.forEach(({ renderingEngineId, viewportId }) => {
const enabledElement = getEnabledElementByIds(
viewportId,
renderingEngineId
);

if (!enabledElement) {
return;
}

const { viewport } = enabledElement;
const { element } = viewport;

const annotations = getAnnotations(element, this.getToolName());

if (annotations?.length) {
annotations.forEach((annotation) => {
removeAnnotation(annotation.annotationUID, element);
});
}
});
}

/**
Expand Down
5 changes: 4 additions & 1 deletion packages/tools/src/utilities/getAnnotationNearPoint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,10 @@ function findAnnotationNearPointByTool(
const { element } = enabledElement.viewport;
for (const annotation of annotations) {
const referencedImageId = annotation.metadata?.referencedImageId;
if (currentId && referencedImageId && currentId !== referencedImageId) {
if (
(currentId && referencedImageId && currentId !== referencedImageId) ||
!tool.isPointNearTool
) {
continue;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,11 @@ class SegmentationRenderingEngine {

const toolGroup = getToolGroupForViewport(viewportId, renderingEngineId);

if (!toolGroup) {
console.warn('toolGroup has been destroyed');
return;
}

const eventDetail: SegmentationRenderedEventDetail = {
toolGroupId: toolGroup.id,
viewportId,
Expand Down
21 changes: 17 additions & 4 deletions packages/tools/src/utilities/triggerAnnotationRender.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,11 @@ class AnnotationRenderingEngine {
// delete element from needsRender if element exist
this._needsRender.delete(element);

// Reset the request animation frame if no enabled elements
if (this._viewportElements.size === 0) {
this._reset();
}
// I don' think there is any disadvantage to canceling the animation frame
// and resetting the flags on viewport's element removal, since the removeVIewportElement
// might be as a result of reEnabling the element (in re-enable we disable first), hence the need to render the
// new one while removing the old one
this._reset();
}

/**
Expand Down Expand Up @@ -105,6 +106,16 @@ class AnnotationRenderingEngine {
}
};

private _setAllViewportsToBeRenderedNextFrame() {
const elements = [...this._viewportElements.values()];

elements.forEach((element) => {
this._needsRender.add(element);
});

this._renderFlaggedViewports();
}

private _setViewportsToBeRenderedNextFrame(elements: HTMLDivElement[]) {
const elementsEnabled = [...this._viewportElements.values()];

Expand Down Expand Up @@ -205,6 +216,8 @@ class AnnotationRenderingEngine {
this._needsRender.clear();
this._animationFrameSet = false;
this._animationFrameHandle = null;

this._setAllViewportsToBeRenderedNextFrame();
}
}

Expand Down

0 comments on commit aeb205e

Please sign in to comment.