@cornerstonejs/tools 1.43.6 → 1.43.7

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.
@@ -0,0 +1,4 @@
1
+ import type { Types } from '@cornerstonejs/core';
2
+ import type { vtkImageData } from '@kitware/vtk.js/Common/DataModel/ImageData';
3
+ import { PointInShapeCallback } from './pointInShapeCallback';
4
+ export default function pointInSurroundingSphereCallback(imageData: vtkImageData, circlePoints: [Types.Point3, Types.Point3], callback: PointInShapeCallback, viewport?: Types.IVolumeViewport): void;
@@ -0,0 +1,70 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const core_1 = require("@cornerstonejs/core");
7
+ const gl_matrix_1 = require("gl-matrix");
8
+ const sphere_1 = require("./math/sphere");
9
+ const pointInShapeCallback_1 = __importDefault(require("./pointInShapeCallback"));
10
+ const boundingBox_1 = require("./boundingBox");
11
+ const { transformWorldToIndex } = core_1.utilities;
12
+ function pointInSurroundingSphereCallback(imageData, circlePoints, callback, viewport) {
13
+ const { boundsIJK, centerWorld, radiusWorld } = _getBounds(circlePoints, imageData, viewport);
14
+ const sphereObj = {
15
+ center: centerWorld,
16
+ radius: radiusWorld,
17
+ };
18
+ (0, pointInShapeCallback_1.default)(imageData, (pointLPS) => (0, sphere_1.pointInSphere)(sphereObj, pointLPS), callback, boundsIJK);
19
+ }
20
+ exports.default = pointInSurroundingSphereCallback;
21
+ function _getBounds(circlePoints, imageData, viewport) {
22
+ const [bottom, top] = circlePoints;
23
+ const centerWorld = gl_matrix_1.vec3.fromValues((bottom[0] + top[0]) / 2, (bottom[1] + top[1]) / 2, (bottom[2] + top[2]) / 2);
24
+ const radiusWorld = gl_matrix_1.vec3.distance(bottom, top) / 2;
25
+ let boundsIJK;
26
+ if (!viewport) {
27
+ const centerIJK = transformWorldToIndex(imageData, centerWorld);
28
+ const spacings = imageData.getSpacing();
29
+ const minSpacing = Math.min(...spacings);
30
+ const maxRadiusIJK = Math.ceil(radiusWorld / minSpacing);
31
+ boundsIJK = [
32
+ [centerIJK[0] - maxRadiusIJK, centerIJK[0] + maxRadiusIJK],
33
+ [centerIJK[1] - maxRadiusIJK, centerIJK[1] + maxRadiusIJK],
34
+ [centerIJK[2] - maxRadiusIJK, centerIJK[2] + maxRadiusIJK],
35
+ ];
36
+ return {
37
+ boundsIJK,
38
+ centerWorld: centerWorld,
39
+ radiusWorld,
40
+ };
41
+ }
42
+ boundsIJK = _computeBoundsIJKWithCamera(imageData, viewport, circlePoints, centerWorld, radiusWorld);
43
+ return {
44
+ boundsIJK,
45
+ centerWorld: centerWorld,
46
+ radiusWorld,
47
+ };
48
+ }
49
+ function _computeBoundsIJKWithCamera(imageData, viewport, circlePoints, centerWorld, radiusWorld) {
50
+ const [bottom, top] = circlePoints;
51
+ const dimensions = imageData.getDimensions();
52
+ const camera = viewport.getCamera();
53
+ const viewUp = gl_matrix_1.vec3.fromValues(camera.viewUp[0], camera.viewUp[1], camera.viewUp[2]);
54
+ const viewPlaneNormal = gl_matrix_1.vec3.fromValues(camera.viewPlaneNormal[0], camera.viewPlaneNormal[1], camera.viewPlaneNormal[2]);
55
+ const viewRight = gl_matrix_1.vec3.create();
56
+ gl_matrix_1.vec3.cross(viewRight, viewUp, viewPlaneNormal);
57
+ const topLeftWorld = gl_matrix_1.vec3.create();
58
+ const bottomRightWorld = gl_matrix_1.vec3.create();
59
+ gl_matrix_1.vec3.scaleAndAdd(topLeftWorld, top, viewPlaneNormal, radiusWorld);
60
+ gl_matrix_1.vec3.scaleAndAdd(bottomRightWorld, bottom, viewPlaneNormal, -radiusWorld);
61
+ gl_matrix_1.vec3.scaleAndAdd(topLeftWorld, topLeftWorld, viewRight, -radiusWorld);
62
+ gl_matrix_1.vec3.scaleAndAdd(bottomRightWorld, bottomRightWorld, viewRight, radiusWorld);
63
+ const sphereCornersIJK = [
64
+ transformWorldToIndex(imageData, topLeftWorld),
65
+ (transformWorldToIndex(imageData, bottomRightWorld)),
66
+ ];
67
+ const boundsIJK = (0, boundingBox_1.getBoundingBoxAroundShape)(sphereCornersIJK, dimensions);
68
+ return boundsIJK;
69
+ }
70
+ //# sourceMappingURL=pointInSurroundingSphereCallback.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pointInSurroundingSphereCallback.js","sourceRoot":"","sources":["../../../src/utilities/pointInSurroundingSphereCallback.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,64 @@
1
+ import { utilities as csUtils } from '@cornerstonejs/core';
2
+ import { vec3 } from 'gl-matrix';
3
+ import { pointInSphere } from './math/sphere';
4
+ import pointInShapeCallback from './pointInShapeCallback';
5
+ import { getBoundingBoxAroundShape } from './boundingBox';
6
+ const { transformWorldToIndex } = csUtils;
7
+ export default function pointInSurroundingSphereCallback(imageData, circlePoints, callback, viewport) {
8
+ const { boundsIJK, centerWorld, radiusWorld } = _getBounds(circlePoints, imageData, viewport);
9
+ const sphereObj = {
10
+ center: centerWorld,
11
+ radius: radiusWorld,
12
+ };
13
+ pointInShapeCallback(imageData, (pointLPS) => pointInSphere(sphereObj, pointLPS), callback, boundsIJK);
14
+ }
15
+ function _getBounds(circlePoints, imageData, viewport) {
16
+ const [bottom, top] = circlePoints;
17
+ const centerWorld = vec3.fromValues((bottom[0] + top[0]) / 2, (bottom[1] + top[1]) / 2, (bottom[2] + top[2]) / 2);
18
+ const radiusWorld = vec3.distance(bottom, top) / 2;
19
+ let boundsIJK;
20
+ if (!viewport) {
21
+ const centerIJK = transformWorldToIndex(imageData, centerWorld);
22
+ const spacings = imageData.getSpacing();
23
+ const minSpacing = Math.min(...spacings);
24
+ const maxRadiusIJK = Math.ceil(radiusWorld / minSpacing);
25
+ boundsIJK = [
26
+ [centerIJK[0] - maxRadiusIJK, centerIJK[0] + maxRadiusIJK],
27
+ [centerIJK[1] - maxRadiusIJK, centerIJK[1] + maxRadiusIJK],
28
+ [centerIJK[2] - maxRadiusIJK, centerIJK[2] + maxRadiusIJK],
29
+ ];
30
+ return {
31
+ boundsIJK,
32
+ centerWorld: centerWorld,
33
+ radiusWorld,
34
+ };
35
+ }
36
+ boundsIJK = _computeBoundsIJKWithCamera(imageData, viewport, circlePoints, centerWorld, radiusWorld);
37
+ return {
38
+ boundsIJK,
39
+ centerWorld: centerWorld,
40
+ radiusWorld,
41
+ };
42
+ }
43
+ function _computeBoundsIJKWithCamera(imageData, viewport, circlePoints, centerWorld, radiusWorld) {
44
+ const [bottom, top] = circlePoints;
45
+ const dimensions = imageData.getDimensions();
46
+ const camera = viewport.getCamera();
47
+ const viewUp = vec3.fromValues(camera.viewUp[0], camera.viewUp[1], camera.viewUp[2]);
48
+ const viewPlaneNormal = vec3.fromValues(camera.viewPlaneNormal[0], camera.viewPlaneNormal[1], camera.viewPlaneNormal[2]);
49
+ const viewRight = vec3.create();
50
+ vec3.cross(viewRight, viewUp, viewPlaneNormal);
51
+ const topLeftWorld = vec3.create();
52
+ const bottomRightWorld = vec3.create();
53
+ vec3.scaleAndAdd(topLeftWorld, top, viewPlaneNormal, radiusWorld);
54
+ vec3.scaleAndAdd(bottomRightWorld, bottom, viewPlaneNormal, -radiusWorld);
55
+ vec3.scaleAndAdd(topLeftWorld, topLeftWorld, viewRight, -radiusWorld);
56
+ vec3.scaleAndAdd(bottomRightWorld, bottomRightWorld, viewRight, radiusWorld);
57
+ const sphereCornersIJK = [
58
+ transformWorldToIndex(imageData, topLeftWorld),
59
+ (transformWorldToIndex(imageData, bottomRightWorld)),
60
+ ];
61
+ const boundsIJK = getBoundingBoxAroundShape(sphereCornersIJK, dimensions);
62
+ return boundsIJK;
63
+ }
64
+ //# sourceMappingURL=pointInSurroundingSphereCallback.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pointInSurroundingSphereCallback.js","sourceRoot":"","sources":["../../../src/utilities/pointInSurroundingSphereCallback.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import type { Types } from '@cornerstonejs/core';
2
+ import type { vtkImageData } from '@kitware/vtk.js/Common/DataModel/ImageData';
3
+ import { PointInShapeCallback } from './pointInShapeCallback';
4
+ export default function pointInSurroundingSphereCallback(imageData: vtkImageData, circlePoints: [Types.Point3, Types.Point3], callback: PointInShapeCallback, viewport?: Types.IVolumeViewport): void;
5
+ //# sourceMappingURL=pointInSurroundingSphereCallback.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pointInSurroundingSphereCallback.d.ts","sourceRoot":"","sources":["../../../src/utilities/pointInSurroundingSphereCallback.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAEjD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4CAA4C,CAAC;AAG/E,OAA6B,EAC3B,oBAAoB,EACrB,MAAM,wBAAwB,CAAC;AAqBhC,MAAM,CAAC,OAAO,UAAU,gCAAgC,CACtD,SAAS,EAAE,YAAY,EACvB,YAAY,EAAE,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,EAC1C,QAAQ,EAAE,oBAAoB,EAC9B,QAAQ,CAAC,EAAE,KAAK,CAAC,eAAe,GAC/B,IAAI,CAsBN"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cornerstonejs/tools",
3
- "version": "1.43.6",
3
+ "version": "1.43.7",
4
4
  "description": "Cornerstone3D Tools",
5
5
  "main": "src/index.ts",
6
6
  "types": "dist/types/index.d.ts",
@@ -29,7 +29,7 @@
29
29
  "webpack:watch": "webpack --mode development --progress --watch --config ./.webpack/webpack.dev.js"
30
30
  },
31
31
  "dependencies": {
32
- "@cornerstonejs/core": "^1.43.6",
32
+ "@cornerstonejs/core": "^1.43.7",
33
33
  "comlink": "^4.4.1",
34
34
  "lodash.clonedeep": "4.5.0",
35
35
  "lodash.get": "^4.4.2"
@@ -53,5 +53,5 @@
53
53
  "type": "individual",
54
54
  "url": "https://ohif.org/donate"
55
55
  },
56
- "gitHead": "66da8823e7582d11c671c88902b2b2be8d6f9617"
56
+ "gitHead": "2d0c559929aa0524bf303922230ded50ac0ef1df"
57
57
  }
@@ -0,0 +1,188 @@
1
+ import { utilities as csUtils } from '@cornerstonejs/core';
2
+ import type { Types } from '@cornerstonejs/core';
3
+
4
+ import type { vtkImageData } from '@kitware/vtk.js/Common/DataModel/ImageData';
5
+ import { vec3 } from 'gl-matrix';
6
+ import { pointInSphere } from './math/sphere';
7
+ import pointInShapeCallback, {
8
+ PointInShapeCallback,
9
+ } from './pointInShapeCallback';
10
+ import { BoundsIJK } from '../types';
11
+ import { getBoundingBoxAroundShape } from './boundingBox';
12
+
13
+ const { transformWorldToIndex } = csUtils;
14
+
15
+ /**
16
+ * Given an imageData, and the great circle top and bottom points of a sphere,
17
+ * this function will run the callback for each point of the imageData that is
18
+ * within the sphere defined by the great circle points. If the viewport
19
+ * is provided, region of interest will be an accurate approximation of the
20
+ * sphere (using viewport camera), and the resulting performance will be
21
+ * better.
22
+ *
23
+ * @privateRemarks great circle also known as orthodrome is the intersection of
24
+ * the sphere and the plane that passes through the center of the sphere
25
+ *
26
+ * @param imageData - The volume imageData
27
+ * @param circlePoints - bottom and top points of the great circle in world coordinates
28
+ * @param callback - A callback function that will be called for each point in the shape.
29
+ */
30
+ export default function pointInSurroundingSphereCallback(
31
+ imageData: vtkImageData,
32
+ circlePoints: [Types.Point3, Types.Point3],
33
+ callback: PointInShapeCallback,
34
+ viewport?: Types.IVolumeViewport
35
+ ): void {
36
+ // We can run the sphere equation to determine if a point is inside
37
+ // the sphere; however, since the imageData dimensions can be quite large, we
38
+ // can narrow down the search by estimating the bounds of the sphere in index
39
+ // space.
40
+ const { boundsIJK, centerWorld, radiusWorld } = _getBounds(
41
+ circlePoints,
42
+ imageData,
43
+ viewport
44
+ );
45
+
46
+ const sphereObj = {
47
+ center: centerWorld,
48
+ radius: radiusWorld,
49
+ };
50
+
51
+ pointInShapeCallback(
52
+ imageData,
53
+ (pointLPS) => pointInSphere(sphereObj, pointLPS),
54
+ callback,
55
+ boundsIJK
56
+ );
57
+ }
58
+
59
+ function _getBounds(
60
+ circlePoints: [Types.Point3, Types.Point3],
61
+ imageData: vtkImageData,
62
+ viewport
63
+ ): {
64
+ boundsIJK: BoundsIJK;
65
+ centerWorld: Types.Point3;
66
+ radiusWorld: number;
67
+ } {
68
+ const [bottom, top] = circlePoints;
69
+
70
+ // Sphere center in world
71
+ const centerWorld = vec3.fromValues(
72
+ (bottom[0] + top[0]) / 2,
73
+ (bottom[1] + top[1]) / 2,
74
+ (bottom[2] + top[2]) / 2
75
+ );
76
+
77
+ // sphere radius in world
78
+ const radiusWorld = vec3.distance(bottom, top) / 2;
79
+
80
+ let boundsIJK;
81
+
82
+ if (!viewport) {
83
+ // If no viewport is provide (no camera), we can estimate the bounding box
84
+ // of the sphere in index space.
85
+ // This is done by calculating the maximum value for radius in the index
86
+ // space (since the radius is in world space, we need to convert it to index, and
87
+ // each dimensions can have a different scale factor). Therefore, by finding
88
+ // the minimum spacing value in the imageData, we can calculate the maximum
89
+ // radius in index space and use that to calculate the bounds of the sphere
90
+ // This will not be accurate, but it is a good first approximation.
91
+ // sphere center in index
92
+ const centerIJK = transformWorldToIndex(
93
+ imageData,
94
+ centerWorld as Types.Point3
95
+ );
96
+
97
+ const spacings = imageData.getSpacing();
98
+ const minSpacing = Math.min(...spacings);
99
+
100
+ const maxRadiusIJK = Math.ceil(radiusWorld / minSpacing);
101
+
102
+ boundsIJK = [
103
+ [centerIJK[0] - maxRadiusIJK, centerIJK[0] + maxRadiusIJK],
104
+ [centerIJK[1] - maxRadiusIJK, centerIJK[1] + maxRadiusIJK],
105
+ [centerIJK[2] - maxRadiusIJK, centerIJK[2] + maxRadiusIJK],
106
+ ];
107
+
108
+ return {
109
+ boundsIJK,
110
+ centerWorld: centerWorld as Types.Point3,
111
+ radiusWorld,
112
+ };
113
+ }
114
+
115
+ boundsIJK = _computeBoundsIJKWithCamera(
116
+ imageData,
117
+ viewport,
118
+ circlePoints,
119
+ centerWorld,
120
+ radiusWorld
121
+ );
122
+
123
+ return {
124
+ boundsIJK,
125
+ centerWorld: centerWorld as Types.Point3,
126
+ radiusWorld,
127
+ };
128
+ }
129
+
130
+ function _computeBoundsIJKWithCamera(
131
+ imageData,
132
+ viewport,
133
+ circlePoints,
134
+ centerWorld,
135
+ radiusWorld
136
+ ) {
137
+ const [bottom, top] = circlePoints;
138
+
139
+ const dimensions = imageData.getDimensions() as Types.Point3;
140
+ const camera = viewport.getCamera();
141
+
142
+ // Calculate viewRight from the camera, this will get used in order to
143
+ // calculate circles topLeft and bottomRight on different planes of intersection
144
+ // between sphere and viewPlane
145
+ const viewUp = vec3.fromValues(
146
+ camera.viewUp[0],
147
+ camera.viewUp[1],
148
+ camera.viewUp[2]
149
+ );
150
+ const viewPlaneNormal = vec3.fromValues(
151
+ camera.viewPlaneNormal[0],
152
+ camera.viewPlaneNormal[1],
153
+ camera.viewPlaneNormal[2]
154
+ );
155
+ const viewRight = vec3.create();
156
+
157
+ vec3.cross(viewRight, viewUp, viewPlaneNormal);
158
+
159
+ // we need to find the bounding box of the sphere in the image, e.g., the
160
+ // topLeftWorld and bottomRightWorld points of the bounding box.
161
+ // We go from the sphereCenter in the normal direction of amount radius, and
162
+ // we go left to find the topLeftWorld point of the bounding box. Next we go
163
+ // in the opposite direction and go right to find the bottomRightWorld point
164
+ // of the bounding box.
165
+ const topLeftWorld = vec3.create();
166
+ const bottomRightWorld = vec3.create();
167
+
168
+ vec3.scaleAndAdd(topLeftWorld, top, viewPlaneNormal, radiusWorld);
169
+ vec3.scaleAndAdd(bottomRightWorld, bottom, viewPlaneNormal, -radiusWorld);
170
+
171
+ // go in the direction of viewRight with the value of radius
172
+ vec3.scaleAndAdd(topLeftWorld, topLeftWorld, viewRight, -radiusWorld);
173
+ vec3.scaleAndAdd(bottomRightWorld, bottomRightWorld, viewRight, radiusWorld);
174
+
175
+ // convert the world coordinates to index coordinates
176
+
177
+ const sphereCornersIJK = [
178
+ <Types.Point3>transformWorldToIndex(imageData, <Types.Point3>topLeftWorld),
179
+ <Types.Point3>(
180
+ transformWorldToIndex(imageData, <Types.Point3>bottomRightWorld)
181
+ ),
182
+ ];
183
+
184
+ // get the bounding box of the sphere in the image
185
+ const boundsIJK = getBoundingBoxAroundShape(sphereCornersIJK, dimensions);
186
+
187
+ return boundsIJK;
188
+ }