@cornerstonejs/core 3.31.0 → 3.31.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,7 +2,7 @@ import type { mat4 } from 'gl-matrix';
2
2
  import type { BlendModes, InterpolationType, OrientationAxis } from '../enums';
3
3
  import type { FlipDirection, IImageData, IVolumeInput, OrientationVectors, Point2, Point3, VolumeViewportProperties, ViewReferenceSpecifier, ReferenceCompatibleOptions, ViewReference, ICamera } from '../types';
4
4
  import type { VoiModifiedEventDetail } from '../types/EventTypes';
5
- import type { ViewportInput } from '../types/IViewport';
5
+ import type { PlaneRestriction, ViewportInput } from '../types/IViewport';
6
6
  import type { TransferFunctionNodes } from '../types/ITransferFunctionNode';
7
7
  import Viewport from './Viewport';
8
8
  import type vtkRenderer from '@kitware/vtk.js/Rendering/Core/Renderer';
@@ -43,6 +43,7 @@ declare abstract class BaseVolumeViewport extends Viewport {
43
43
  isReferenceViewable(viewRef: ViewReference, options?: ReferenceCompatibleOptions): boolean;
44
44
  scroll(delta?: number): void;
45
45
  abstract isInAcquisitionPlane(): boolean;
46
+ setViewPlane(planeRestriction: PlaneRestriction, viewPlaneNormal: any): void;
46
47
  setViewReference(viewRef: ViewReference): void;
47
48
  private setThreshold;
48
49
  setProperties({ voiRange, VOILUTFunction, invert, colormap, preset, interpolationType, slabThickness, }?: VolumeViewportProperties, volumeId?: string, suppressEvents?: boolean): void;
@@ -78,6 +79,7 @@ declare abstract class BaseVolumeViewport extends Viewport {
78
79
  getRendererContextPool(): vtkRenderer;
79
80
  getRendererTiled(): vtkRenderer;
80
81
  hasImageURI: (imageURI: string) => boolean;
82
+ protected _getViewUp(viewPlaneNormal: any): Point3;
81
83
  protected _getOrientationVectors(orientation: OrientationAxis | OrientationVectors): OrientationVectors;
82
84
  protected _getAcquisitionPlaneOrientation(): OrientationVectors;
83
85
  getSlabThickness(): number;
@@ -23,7 +23,7 @@ import getVolumeViewportScrollInfo from '../utilities/getVolumeViewportScrollInf
23
23
  import { actorIsA, isImageActor } from '../utilities/actorCheck';
24
24
  import snapFocalPointToSlice from '../utilities/snapFocalPointToSlice';
25
25
  import getVoiFromSigmoidRGBTransferFunction from '../utilities/getVoiFromSigmoidRGBTransferFunction';
26
- import isEqual, { isEqualNegative } from '../utilities/isEqual';
26
+ import isEqual, { isEqualAbs, isEqualNegative } from '../utilities/isEqual';
27
27
  import applyPreset from '../utilities/applyPreset';
28
28
  import imageIdToURI from '../utilities/imageIdToURI';
29
29
  import uuidv4 from '../utilities/uuidv4';
@@ -257,11 +257,11 @@ class BaseVolumeViewport extends Viewport {
257
257
  const volumeActors = this.getActors().filter((actorEntry) => actorIsA(actorEntry, 'vtkVolume'));
258
258
  return volumeActors.some(({ uid, referencedId }) => {
259
259
  const volume = cache.getVolume(referencedId || uid);
260
- if (!volume?.imageIds) {
260
+ if (!volume?.getImageIdIndex) {
261
261
  return false;
262
262
  }
263
- const volumeImageURIs = volume.imageIds.map(imageIdToURI);
264
- return volumeImageURIs.includes(imageURI);
263
+ return (volume.getImageIdIndex(imageURI) !== undefined ||
264
+ volume.getImageURIIndex(imageURI) !== undefined);
265
265
  });
266
266
  };
267
267
  this.getImageIds = (volumeId) => {
@@ -580,7 +580,8 @@ class BaseVolumeViewport extends Viewport {
580
580
  return false;
581
581
  }
582
582
  if (options?.withNavigation) {
583
- return true;
583
+ const { referencedImageId } = viewRef;
584
+ return !referencedImageId || this.hasImageURI(referencedImageId);
584
585
  }
585
586
  const currentSliceIndex = this.getSliceIndex();
586
587
  const { sliceIndex } = viewRef;
@@ -604,14 +605,50 @@ class BaseVolumeViewport extends Viewport {
604
605
  });
605
606
  this.render();
606
607
  }
608
+ setViewPlane(planeRestriction, viewPlaneNormal) {
609
+ const { point, inPlaneVector1, inPlaneVector2, FrameOfReferenceUID } = planeRestriction;
610
+ if (!inPlaneVector1) {
611
+ return this.setViewReference({
612
+ FrameOfReferenceUID,
613
+ cameraFocalPoint: point,
614
+ });
615
+ }
616
+ if (inPlaneVector2) {
617
+ const planeNormal = (vec3.cross(vec3.create(), inPlaneVector1, inPlaneVector2));
618
+ vec3.normalize(planeNormal, planeNormal);
619
+ return this.setViewReference({
620
+ FrameOfReferenceUID,
621
+ cameraFocalPoint: point,
622
+ viewPlaneNormal: planeNormal,
623
+ });
624
+ }
625
+ const dotNormal = vec3.dot(viewPlaneNormal, inPlaneVector1);
626
+ if (isEqual(dotNormal, 0)) {
627
+ return this.setViewReference({
628
+ FrameOfReferenceUID,
629
+ viewPlaneNormal,
630
+ cameraFocalPoint: point,
631
+ });
632
+ }
633
+ const planeNormal = (vec3.cross(vec3.create(), viewPlaneNormal, inPlaneVector1));
634
+ vec3.normalize(planeNormal, planeNormal);
635
+ return this.setViewReference({
636
+ FrameOfReferenceUID,
637
+ viewPlaneNormal: planeNormal,
638
+ cameraFocalPoint: point,
639
+ });
640
+ }
607
641
  setViewReference(viewRef) {
608
642
  if (!viewRef) {
609
643
  return;
610
644
  }
611
645
  const volumeId = this.getVolumeId();
612
- const { viewPlaneNormal: refViewPlaneNormal, FrameOfReferenceUID: refFrameOfReference, cameraFocalPoint, referencedImageId, viewUp, } = viewRef;
646
+ const { FrameOfReferenceUID: refFrameOfReference, cameraFocalPoint, referencedImageId, planeRestriction, viewPlaneNormal: refViewPlaneNormal, viewUp, } = viewRef;
613
647
  let { sliceIndex } = viewRef;
614
648
  const { focalPoint, viewPlaneNormal, position } = this.getCamera();
649
+ if (planeRestriction?.inPlaneVector1 && !refViewPlaneNormal) {
650
+ return this.setViewPlane(planeRestriction, viewPlaneNormal);
651
+ }
615
652
  const isNegativeNormal = isEqualNegative(viewPlaneNormal, refViewPlaneNormal);
616
653
  const isSameNormal = isEqual(viewPlaneNormal, refViewPlaneNormal);
617
654
  if (typeof sliceIndex === 'number' &&
@@ -969,13 +1006,35 @@ class BaseVolumeViewport extends Viewport {
969
1006
  }
970
1007
  return renderingEngine.offscreenMultiRenderWindow?.getRenderer(this.id);
971
1008
  }
1009
+ _getViewUp(viewPlaneNormal) {
1010
+ const { viewUp } = this.getCamera();
1011
+ const dot = vec3.dot(viewUp, viewPlaneNormal);
1012
+ if (isEqual(dot, 0)) {
1013
+ return viewUp;
1014
+ }
1015
+ if (isEqualAbs(viewPlaneNormal[0], 1)) {
1016
+ return [0, 0, 1];
1017
+ }
1018
+ if (isEqualAbs(viewPlaneNormal[1], 1)) {
1019
+ return [0, 0, 1];
1020
+ }
1021
+ if (isEqualAbs(viewPlaneNormal[2], 1)) {
1022
+ return [0, -1, 0];
1023
+ }
1024
+ const vupOrthogonal = (vec3.scaleAndAdd(vec3.create(), viewUp, viewPlaneNormal, -dot));
1025
+ vec3.normalize(vupOrthogonal, vupOrthogonal);
1026
+ return vupOrthogonal;
1027
+ }
972
1028
  _getOrientationVectors(orientation) {
973
1029
  if (typeof orientation === 'object') {
974
- if (orientation.viewPlaneNormal && orientation.viewUp) {
975
- return orientation;
1030
+ if (orientation.viewPlaneNormal) {
1031
+ return {
1032
+ ...orientation,
1033
+ viewUp: orientation.viewUp || this._getViewUp(orientation.viewPlaneNormal),
1034
+ };
976
1035
  }
977
1036
  else {
978
- throw new Error('Invalid orientation object. It must contain viewPlaneNormal and viewUp');
1037
+ throw new Error('Invalid orientation object. It must contain viewPlaneNormal');
979
1038
  }
980
1039
  }
981
1040
  else if (typeof orientation === 'string') {
@@ -1794,10 +1794,13 @@ class StackViewport extends Viewport {
1794
1794
  this.imageKeyToIndexMap.get(multiSliceReference.referencedImageId);
1795
1795
  return testIndex <= rangeEndSliceIndex && testIndex >= foundSliceIndex;
1796
1796
  }
1797
- if (!super.isReferenceViewable(viewRef, options)) {
1797
+ if (!super.isReferenceViewable(viewRef, {
1798
+ ...options,
1799
+ withOrientation: options?.asVolume,
1800
+ })) {
1798
1801
  return false;
1799
1802
  }
1800
- if (viewRef.volumeId) {
1803
+ if (viewRef.volumeId || viewRef.FrameOfReferenceUID) {
1801
1804
  return options.asVolume;
1802
1805
  }
1803
1806
  const { cameraFocalPoint } = viewRef;
@@ -574,7 +574,7 @@ class VideoViewport extends Viewport {
574
574
  }
575
575
  }
576
576
  getCurrentImageId(index = this.getCurrentImageIdIndex()) {
577
- const current = this.imageId.replace('/frames/1', `/frames/${index + 1}`);
577
+ const current = this.imageId?.replace('/frames/1', `/frames/${index + 1}`);
578
578
  return current;
579
579
  }
580
580
  getViewReferenceId(specifier = {}) {
@@ -4,7 +4,7 @@ import type { mat4 } from 'gl-matrix';
4
4
  import ViewportStatus from '../enums/ViewportStatus';
5
5
  import ViewportType from '../enums/ViewportType';
6
6
  import type { ICamera, ActorEntry, IRenderingEngine, ViewportInputOptions, Point2, Point3, FlipDirection, DisplayArea, ViewPresentation, ViewReference, ViewportProperties, ImageActor } from '../types';
7
- import type { ViewportInput, ViewReferenceSpecifier, ReferenceCompatibleOptions, ViewPresentationSelector, DataSetOptions } from '../types/IViewport';
7
+ import type { ViewportInput, ViewReferenceSpecifier, ReferenceCompatibleOptions, ViewPresentationSelector, DataSetOptions, PlaneRestriction } from '../types/IViewport';
8
8
  import type { vtkSlabCamera } from './vtkClasses/vtkSlabCamera';
9
9
  import type IImageCalibration from '../types/IImageCalibration';
10
10
  import { InterpolationType } from '../enums';
@@ -121,6 +121,7 @@ declare class Viewport {
121
121
  getClippingPlanesForActor(actorEntry?: ActorEntry): vtkPlane[];
122
122
  private _getWorldDistanceViewUpAndViewRight;
123
123
  getViewReference(viewRefSpecifier?: ViewReferenceSpecifier): ViewReference;
124
+ isPlaneViewable(planeRestriction: PlaneRestriction, options?: ReferenceCompatibleOptions): boolean;
124
125
  isReferenceViewable(viewRef: ViewReference, options?: ReferenceCompatibleOptions): boolean;
125
126
  getViewPresentation(viewPresSel?: ViewPresentationSelector): ViewPresentation;
126
127
  setViewReference(viewRef: ViewReference): void;
@@ -14,6 +14,7 @@ import hasNaNValues from '../utilities/hasNaNValues';
14
14
  import { RENDERING_DEFAULTS } from '../constants';
15
15
  import { InterpolationType } from '../enums';
16
16
  import { deepClone } from '../utilities/deepClone';
17
+ import { updatePlaneRestriction } from '../utilities/updatePlaneRestriction';
17
18
  class Viewport {
18
19
  static { this.CameraViewPresentation = {
19
20
  rotation: true,
@@ -906,16 +907,52 @@ class Viewport {
906
907
  }
907
908
  getViewReference(viewRefSpecifier) {
908
909
  const { focalPoint: cameraFocalPoint, viewPlaneNormal, viewUp, } = this.getCamera();
910
+ const FrameOfReferenceUID = this.getFrameOfReferenceUID();
909
911
  const target = {
910
- FrameOfReferenceUID: this.getFrameOfReferenceUID(),
912
+ FrameOfReferenceUID,
911
913
  cameraFocalPoint,
912
914
  viewPlaneNormal,
913
915
  viewUp,
914
916
  sliceIndex: viewRefSpecifier?.sliceIndex ?? this.getSliceIndex(),
917
+ planeRestriction: {
918
+ FrameOfReferenceUID,
919
+ point: viewRefSpecifier?.points?.[0] || cameraFocalPoint,
920
+ inPlaneVector1: viewUp,
921
+ inPlaneVector2: (vec3.cross(vec3.create(), viewUp, viewPlaneNormal)),
922
+ },
915
923
  };
924
+ if (viewRefSpecifier?.points) {
925
+ updatePlaneRestriction(viewRefSpecifier.points, target.planeRestriction);
926
+ }
916
927
  return target;
917
928
  }
929
+ isPlaneViewable(planeRestriction, options) {
930
+ if (planeRestriction.FrameOfReferenceUID !== this.getFrameOfReferenceUID()) {
931
+ return false;
932
+ }
933
+ const { focalPoint, viewPlaneNormal } = this.getCamera();
934
+ const { point, inPlaneVector1, inPlaneVector2 } = planeRestriction;
935
+ if (options?.withOrientation) {
936
+ return true;
937
+ }
938
+ if (inPlaneVector1 &&
939
+ !isEqual(0, vec3.dot(viewPlaneNormal, inPlaneVector1))) {
940
+ return false;
941
+ }
942
+ if (inPlaneVector2 &&
943
+ !isEqual(0, vec3.dot(viewPlaneNormal, inPlaneVector2))) {
944
+ return false;
945
+ }
946
+ if (options?.withNavigation) {
947
+ return true;
948
+ }
949
+ const pointVector = vec3.sub(vec3.create(), point, focalPoint);
950
+ return isEqual(0, vec3.dot(pointVector, viewPlaneNormal));
951
+ }
918
952
  isReferenceViewable(viewRef, options) {
953
+ if (viewRef.planeRestriction) {
954
+ return this.isPlaneViewable(viewRef.planeRestriction, options);
955
+ }
919
956
  if (viewRef.FrameOfReferenceUID &&
920
957
  viewRef.FrameOfReferenceUID !== this.getFrameOfReferenceUID()) {
921
958
  return false;
@@ -24,8 +24,15 @@ export interface ReferenceCompatibleOptions {
24
24
  export type ReferencedImageRange = ViewReference & {
25
25
  referencedImageId: string;
26
26
  };
27
- export type ViewReference = {
27
+ export type PlaneRestriction = {
28
+ FrameOfReferenceUID: string;
29
+ point: Point3;
30
+ inPlaneVector1?: Point3;
31
+ inPlaneVector2?: Point3;
32
+ };
33
+ export interface ViewReference {
28
34
  FrameOfReferenceUID?: string;
35
+ planeRestriction?: PlaneRestriction;
29
36
  referencedImageId?: string;
30
37
  referencedImageURI?: string;
31
38
  multiSliceReference?: ReferencedImageRange;
@@ -35,7 +42,7 @@ export type ViewReference = {
35
42
  sliceIndex?: number;
36
43
  volumeId?: string;
37
44
  bounds?: BoundsLPS;
38
- };
45
+ }
39
46
  export interface ViewPresentation {
40
47
  slabThickness?: number;
41
48
  rotation?: number;
@@ -94,6 +94,7 @@ export * as logger from './logger';
94
94
  import { calculateNeighborhoodStats } from './calculateNeighborhoodStats';
95
95
  import getPixelSpacingInformation from './getPixelSpacingInformation';
96
96
  import { asArray } from './asArray';
97
+ export { updatePlaneRestriction } from './updatePlaneRestriction';
97
98
  declare const getViewportModality: (viewport: IViewport, volumeId?: string) => string;
98
99
  export * from './isEqual';
99
100
  export { FrameRange, eventListener, csUtils as invertRgbTransferFunction, createSigmoidRGBTransferFunction, getVoiFromSigmoidRGBTransferFunction, createLinearRGBTransferFunction, scaleRgbTransferFunction, triggerEvent, imageIdToURI, fnv1aHash, calibratedPixelSpacingMetadataProvider, clamp, uuidv4, getMinMax, getRuntimeId, isOpposite, getViewportModality, windowLevel, convertToGrayscale, getClosestImageId, getSpacingInNormalDirection, getTargetVolumeAndSpacingInNormalDir, getVolumeActorCorners, indexWithinDimensions, getVolumeViewportsContainingSameVolumes, getViewportsWithVolumeId, transformWorldToIndex, transformIndexToWorld, loadImageToCanvas, renderToCanvasCPU, renderToCanvasGPU, worldToImageCoords, imageToWorldCoords, getVolumeSliceRangeInfo, getVolumeViewportScrollInfo, getSliceRange, snapFocalPointToSlice, getImageSliceDataForVolumeViewport, isImageActor, isPTPrescaledWithSUV, actorIsA, getViewportsWithImageURI, getClosestStackImageIndexForPoint, getCurrentVolumeViewportSlice, calculateViewportsSpatialRegistration, spatialRegistrationMetadataProvider, getViewportImageCornersInWorld, hasNaNValues, applyPreset, deepMerge, PointsManager, getScalingParameters, colormap, getImageLegacy, ProgressiveIterator, decimate, imageRetrieveMetadataProvider, transferFunctionUtils, updateVTKImageDataWithCornerstoneImage, sortImageIdsAndGetSpacing, makeVolumeMetadata, isValidVolume, genericMetadataProvider, isVideoTransferSyntax, HistoryMemo, generateVolumePropsFromImageIds, getBufferConfiguration, VoxelManager, RLEVoxelMap, convertStackToVolumeViewport, convertVolumeToStackViewport, roundNumber, roundToPrecision, getViewportImageIds, getRandomSampleFromArray, getVolumeId, color, hasFloatScalingParameters, getDynamicVolumeInfo, autoLoad, scaleArray, deepClone, splitImageIdsBy4DTags, pointInShapeCallback, deepEqual, jumpToSlice, scroll, clip, transformWorldToIndexContinuous, createSubVolume, getVolumeDirectionVectors, calculateSpacingBetweenImageIds, getImageDataMetadata, buildMetadata, calculateNeighborhoodStats, getPixelSpacingInformation, asArray, };
@@ -95,6 +95,7 @@ export * as logger from './logger';
95
95
  import { calculateNeighborhoodStats } from './calculateNeighborhoodStats';
96
96
  import getPixelSpacingInformation from './getPixelSpacingInformation';
97
97
  import { asArray } from './asArray';
98
+ export { updatePlaneRestriction } from './updatePlaneRestriction';
98
99
  const getViewportModality = (viewport, volumeId) => _getViewportModality(viewport, volumeId, cache.getVolume);
99
100
  export * from './isEqual';
100
101
  export { FrameRange, eventListener, csUtils as invertRgbTransferFunction, createSigmoidRGBTransferFunction, getVoiFromSigmoidRGBTransferFunction, createLinearRGBTransferFunction, scaleRgbTransferFunction, triggerEvent, imageIdToURI, fnv1aHash, calibratedPixelSpacingMetadataProvider, clamp, uuidv4, getMinMax, getRuntimeId, isOpposite, getViewportModality, windowLevel, convertToGrayscale, getClosestImageId, getSpacingInNormalDirection, getTargetVolumeAndSpacingInNormalDir, getVolumeActorCorners, indexWithinDimensions, getVolumeViewportsContainingSameVolumes, getViewportsWithVolumeId, transformWorldToIndex, transformIndexToWorld, loadImageToCanvas, renderToCanvasCPU, renderToCanvasGPU, worldToImageCoords, imageToWorldCoords, getVolumeSliceRangeInfo, getVolumeViewportScrollInfo, getSliceRange, snapFocalPointToSlice, getImageSliceDataForVolumeViewport, isImageActor, isPTPrescaledWithSUV, actorIsA, getViewportsWithImageURI, getClosestStackImageIndexForPoint, getCurrentVolumeViewportSlice, calculateViewportsSpatialRegistration, spatialRegistrationMetadataProvider, getViewportImageCornersInWorld, hasNaNValues, applyPreset, deepMerge, PointsManager, getScalingParameters, colormap, getImageLegacy, ProgressiveIterator, decimate, imageRetrieveMetadataProvider, transferFunctionUtils, updateVTKImageDataWithCornerstoneImage, sortImageIdsAndGetSpacing, makeVolumeMetadata, isValidVolume, genericMetadataProvider, isVideoTransferSyntax, HistoryMemo, generateVolumePropsFromImageIds, getBufferConfiguration, VoxelManager, RLEVoxelMap, convertStackToVolumeViewport, convertVolumeToStackViewport, roundNumber, roundToPrecision, getViewportImageIds, getRandomSampleFromArray, getVolumeId, color, hasFloatScalingParameters, getDynamicVolumeInfo, autoLoad, scaleArray, deepClone, splitImageIdsBy4DTags, pointInShapeCallback, deepEqual, jumpToSlice, scroll, clip, transformWorldToIndexContinuous, createSubVolume, getVolumeDirectionVectors, calculateSpacingBetweenImageIds, getImageDataMetadata, buildMetadata, calculateNeighborhoodStats, getPixelSpacingInformation, asArray, };
@@ -1,5 +1,5 @@
1
- export default function isEqual<ValueType>(v1: ValueType, v2: ValueType, tolerance?: number): boolean;
2
- declare const isEqualNegative: <ValueType>(v1: ValueType, v2: ValueType, tolerance?: any) => boolean;
3
- declare const isEqualAbs: <ValueType>(v1: ValueType, v2: ValueType, tolerance?: any) => boolean;
4
- declare function isNumber(n: number[] | number): boolean;
5
- export { isEqualNegative, isEqual, isEqualAbs, isNumber };
1
+ export declare function isEqual<ValueType>(v1: ValueType, v2: ValueType, tolerance?: number): boolean;
2
+ export declare const isEqualNegative: <ValueType>(v1: ValueType, v2: ValueType, tolerance?: any) => boolean;
3
+ export declare const isEqualAbs: <ValueType>(v1: ValueType, v2: ValueType, tolerance?: any) => boolean;
4
+ export declare function isNumber(n: number[] | number): boolean;
5
+ export default isEqual;
@@ -23,7 +23,7 @@ function isNumberArrayLike(value) {
23
23
  value.length > 0 &&
24
24
  typeof value[0] === 'number');
25
25
  }
26
- export default function isEqual(v1, v2, tolerance = 1e-5) {
26
+ export function isEqual(v1, v2, tolerance = 1e-5) {
27
27
  if (typeof v1 !== typeof v2 || v1 === null || v2 === null) {
28
28
  return false;
29
29
  }
@@ -37,12 +37,12 @@ export default function isEqual(v1, v2, tolerance = 1e-5) {
37
37
  }
38
38
  const negative = (v) => typeof v === 'number' ? -v : v?.map ? v.map(negative) : !v;
39
39
  const abs = (v) => typeof v === 'number' ? Math.abs(v) : v?.map ? v.map(abs) : v;
40
- const isEqualNegative = (v1, v2, tolerance = undefined) => isEqual(v1, negative(v2), tolerance);
41
- const isEqualAbs = (v1, v2, tolerance = undefined) => isEqual(abs(v1), abs(v2), tolerance);
42
- function isNumber(n) {
40
+ export const isEqualNegative = (v1, v2, tolerance = undefined) => isEqual(v1, negative(v2), tolerance);
41
+ export const isEqualAbs = (v1, v2, tolerance = undefined) => isEqual(abs(v1), abs(v2), tolerance);
42
+ export function isNumber(n) {
43
43
  if (Array.isArray(n)) {
44
44
  return isNumber(n[0]);
45
45
  }
46
46
  return isFinite(n) && !isNaN(n);
47
47
  }
48
- export { isEqualNegative, isEqual, isEqualAbs, isNumber };
48
+ export default isEqual;
@@ -0,0 +1,2 @@
1
+ import type { Point3, ViewReference } from '../types';
2
+ export declare function updatePlaneRestriction(points: Point3[], reference: ViewReference): import("../types/IViewport").PlaneRestriction;
@@ -0,0 +1,41 @@
1
+ import { isEqual } from '../utilities/isEqual';
2
+ import { vec3 } from 'gl-matrix';
3
+ const ORTHOGONAL_TEST_VALUE = 0.95;
4
+ export function updatePlaneRestriction(points, reference) {
5
+ if (!points?.length || !reference.FrameOfReferenceUID) {
6
+ return;
7
+ }
8
+ reference.planeRestriction ||= {
9
+ FrameOfReferenceUID: reference.FrameOfReferenceUID,
10
+ point: points[0],
11
+ inPlaneVector1: null,
12
+ inPlaneVector2: null,
13
+ };
14
+ const { planeRestriction } = reference;
15
+ if (points.length === 1) {
16
+ planeRestriction.inPlaneVector1 = null;
17
+ planeRestriction.inPlaneVector2 = null;
18
+ return planeRestriction;
19
+ }
20
+ const v1 = vec3.sub(vec3.create(), points[0], points[Math.floor(points.length / 2)]);
21
+ vec3.normalize(v1, v1);
22
+ planeRestriction.inPlaneVector1 = v1;
23
+ planeRestriction.inPlaneVector2 = null;
24
+ const n = points.length;
25
+ if (n > 2) {
26
+ for (let i = Math.floor(n / 3); i < n; i++) {
27
+ const testVector = vec3.sub(vec3.create(), points[i], points[0]);
28
+ const length = vec3.length(testVector);
29
+ if (isEqual(length, 0)) {
30
+ continue;
31
+ }
32
+ if (vec3.dot(testVector, planeRestriction.inPlaneVector1) <
33
+ length * ORTHOGONAL_TEST_VALUE) {
34
+ vec3.normalize(testVector, testVector);
35
+ planeRestriction.inPlaneVector2 = testVector;
36
+ return planeRestriction;
37
+ }
38
+ }
39
+ }
40
+ return planeRestriction;
41
+ }
@@ -1 +1 @@
1
- export declare const version = "3.31.0";
1
+ export declare const version = "3.31.1";
@@ -1 +1 @@
1
- export const version = '3.31.0';
1
+ export const version = '3.31.1';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cornerstonejs/core",
3
- "version": "3.31.0",
3
+ "version": "3.31.1",
4
4
  "description": "Cornerstone3D Core",
5
5
  "module": "./dist/esm/index.js",
6
6
  "types": "./dist/esm/index.d.ts",
@@ -97,5 +97,5 @@
97
97
  "type": "individual",
98
98
  "url": "https://ohif.org/donate"
99
99
  },
100
- "gitHead": "ea3e44970a9e535db1f38c8186653ffb7376ecf9"
100
+ "gitHead": "0fc65e9cc1d86a9a8b97ee9e7eb5802ce5e1e635"
101
101
  }