@cornerstonejs/polymorphic-segmentation 3.21.1 → 3.22.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.
- package/dist/esm/Contour/utils/createAndAddContourSegmentationsFromClippedSurfaces.js +94 -1
- package/dist/esm/Contour/utils/extractContourData.js +3 -0
- package/dist/esm/Surface/convertContourToSurface.js +3 -0
- package/dist/esm/version.d.ts +1 -1
- package/dist/esm/version.js +1 -1
- package/dist/esm/workers/polySegConverters.js +25 -9
- package/package.json +4 -4
|
@@ -1,11 +1,104 @@
|
|
|
1
1
|
import { utilities } from '@cornerstonejs/core';
|
|
2
2
|
import { PlanarFreehandContourSegmentationTool, annotation, } from '@cornerstonejs/tools';
|
|
3
|
+
import { vec3 } from 'gl-matrix';
|
|
4
|
+
function findBestContourForNormalCalculation(lines, minPreferredPoints = 3) {
|
|
5
|
+
let bestContourIndex = 0;
|
|
6
|
+
let bestCount = 0;
|
|
7
|
+
let currentIndex = 0;
|
|
8
|
+
while (currentIndex < lines.length) {
|
|
9
|
+
const count = lines[currentIndex];
|
|
10
|
+
if (count < 2) {
|
|
11
|
+
currentIndex += count + 1;
|
|
12
|
+
continue;
|
|
13
|
+
}
|
|
14
|
+
if (count > minPreferredPoints && bestCount <= minPreferredPoints) {
|
|
15
|
+
bestContourIndex = currentIndex;
|
|
16
|
+
bestCount = count;
|
|
17
|
+
break;
|
|
18
|
+
}
|
|
19
|
+
else if (count > bestCount) {
|
|
20
|
+
bestContourIndex = currentIndex;
|
|
21
|
+
bestCount = count;
|
|
22
|
+
}
|
|
23
|
+
currentIndex += count + 1;
|
|
24
|
+
}
|
|
25
|
+
if (bestCount < 2) {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
const pointIndices = lines.slice(bestContourIndex + 1, bestContourIndex + 1 + bestCount);
|
|
29
|
+
return {
|
|
30
|
+
contourIndex: bestContourIndex,
|
|
31
|
+
pointCount: bestCount,
|
|
32
|
+
pointIndices,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
function isPolylineParallelToPlane(lines, points, planeNormal, dotProductTolerance = 0.99) {
|
|
36
|
+
const bestContour = findBestContourForNormalCalculation(lines);
|
|
37
|
+
if (!bestContour) {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
const { pointCount: count, pointIndices: ids } = bestContour;
|
|
41
|
+
const _p_v1 = vec3.create();
|
|
42
|
+
const _p_v2 = vec3.create();
|
|
43
|
+
const _p_p0 = vec3.create();
|
|
44
|
+
const _p_p1 = vec3.create();
|
|
45
|
+
const _p_p2 = vec3.create();
|
|
46
|
+
const _p_polylineNormal = vec3.create();
|
|
47
|
+
const _p_planeNormal = vec3.create();
|
|
48
|
+
vec3.set(_p_p0, points[ids[0] * 3], points[ids[0] * 3 + 1], points[ids[0] * 3 + 2]);
|
|
49
|
+
let p1_found = false;
|
|
50
|
+
for (let i = 1; i < count; i++) {
|
|
51
|
+
vec3.set(_p_p1, points[ids[i] * 3], points[ids[i] * 3 + 1], points[ids[i] * 3 + 2]);
|
|
52
|
+
if (!vec3.equals(_p_p0, _p_p1)) {
|
|
53
|
+
p1_found = true;
|
|
54
|
+
break;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
if (!p1_found) {
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
vec3.subtract(_p_v1, _p_p1, _p_p0);
|
|
61
|
+
let p2_found = false;
|
|
62
|
+
for (let i = 2; i < count; i++) {
|
|
63
|
+
vec3.set(_p_p2, points[ids[i] * 3], points[ids[i] * 3 + 1], points[ids[i] * 3 + 2]);
|
|
64
|
+
vec3.subtract(_p_v2, _p_p2, _p_p0);
|
|
65
|
+
vec3.cross(_p_polylineNormal, _p_v1, _p_v2);
|
|
66
|
+
if (vec3.length(_p_polylineNormal) > 1e-6) {
|
|
67
|
+
p2_found = true;
|
|
68
|
+
break;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
vec3.normalize(_p_planeNormal, planeNormal);
|
|
72
|
+
if (p2_found) {
|
|
73
|
+
vec3.normalize(_p_polylineNormal, _p_polylineNormal);
|
|
74
|
+
const dot = vec3.dot(_p_polylineNormal, _p_planeNormal);
|
|
75
|
+
return Math.abs(dot) >= dotProductTolerance;
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
vec3.normalize(_p_v1, _p_v1);
|
|
79
|
+
const dot = vec3.dot(_p_v1, _p_planeNormal);
|
|
80
|
+
return Math.abs(dot) >= dotProductTolerance;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
3
83
|
const { addAnnotation } = annotation.state;
|
|
4
84
|
export function createAndAddContourSegmentationsFromClippedSurfaces(rawContourData, viewport, segmentationId) {
|
|
5
85
|
const annotationUIDsMap = new Map();
|
|
86
|
+
if (!viewport) {
|
|
87
|
+
console.warn('Invalid viewport given');
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
const camera = viewport.getCamera();
|
|
91
|
+
if (!camera) {
|
|
92
|
+
console.warn('Camera not available in viewport');
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
const planeNormal = camera.viewPlaneNormal;
|
|
6
96
|
for (const [segmentIndex, contoursData] of rawContourData) {
|
|
7
97
|
for (const contourData of contoursData) {
|
|
8
|
-
const { points } = contourData;
|
|
98
|
+
const { points, lines } = contourData;
|
|
99
|
+
if (!isPolylineParallelToPlane(lines, points, planeNormal)) {
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
9
102
|
const { lineSegments, linesNumberOfPoints } = _extractLineSegments(contourData);
|
|
10
103
|
for (let i = 0; i < lineSegments.length; i++) {
|
|
11
104
|
const line = lineSegments[i];
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
export function extractContourData(polyDataCache) {
|
|
2
2
|
const rawResults = new Map();
|
|
3
|
+
if (!polyDataCache) {
|
|
4
|
+
return rawResults;
|
|
5
|
+
}
|
|
3
6
|
for (const [segmentIndex, intersectionInfo] of polyDataCache) {
|
|
4
7
|
const segmentIndexNumber = Number(segmentIndex);
|
|
5
8
|
for (const [_, result] of intersectionInfo) {
|
|
@@ -15,6 +15,9 @@ export async function convertContourToSurface(contourRepresentationData, segment
|
|
|
15
15
|
const polylines = [];
|
|
16
16
|
const numPointsArray = [];
|
|
17
17
|
const annotationUIDs = annotationUIDsMap.get(segmentIndex);
|
|
18
|
+
if (!annotationUIDs) {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
18
21
|
for (const annotationUID of annotationUIDs) {
|
|
19
22
|
const annotation = getAnnotation(annotationUID);
|
|
20
23
|
const { polyline } = annotation.data.contour;
|
package/dist/esm/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const version = "3.
|
|
1
|
+
export declare const version = "3.22.1";
|
package/dist/esm/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const version = '3.
|
|
1
|
+
export const version = '3.22.1';
|
|
@@ -348,7 +348,7 @@ const polySegConverters = {
|
|
|
348
348
|
continue;
|
|
349
349
|
}
|
|
350
350
|
surfacePolyData.getPoints().setData(points, 3);
|
|
351
|
-
surfacePolyData.getPolys().setData(polys
|
|
351
|
+
surfacePolyData.getPolys().setData(polys);
|
|
352
352
|
surfacePolyData.modified();
|
|
353
353
|
cutter.setInputData(surfacePolyData);
|
|
354
354
|
plane1.setOrigin(origin);
|
|
@@ -361,18 +361,34 @@ const polySegConverters = {
|
|
|
361
361
|
continue;
|
|
362
362
|
}
|
|
363
363
|
const polyData = cutter.getOutputData();
|
|
364
|
+
if (!polyData ||
|
|
365
|
+
!polyData.getPoints() ||
|
|
366
|
+
polyData.getPoints().getNumberOfPoints() === 0) {
|
|
367
|
+
continue;
|
|
368
|
+
}
|
|
364
369
|
const cutterOutput = polyData;
|
|
365
370
|
cutterOutput.buildLinks();
|
|
366
371
|
const loopExtraction = vtkContourLoopExtraction.newInstance();
|
|
367
372
|
loopExtraction.setInputData(cutterOutput);
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
373
|
+
try {
|
|
374
|
+
loopExtraction.update();
|
|
375
|
+
const loopOutput = loopExtraction.getOutputData();
|
|
376
|
+
if (loopOutput &&
|
|
377
|
+
loopOutput.getPoints() &&
|
|
378
|
+
loopOutput.getLines() &&
|
|
379
|
+
loopOutput.getPoints().getNumberOfPoints() > 0 &&
|
|
380
|
+
loopOutput.getLines().getNumberOfCells() > 0) {
|
|
381
|
+
polyDataResults.set(segmentIndex, {
|
|
382
|
+
points: loopOutput.getPoints().getData(),
|
|
383
|
+
lines: loopOutput.getLines().getData(),
|
|
384
|
+
numberOfCells: loopOutput.getLines().getNumberOfCells(),
|
|
385
|
+
segmentIndex,
|
|
386
|
+
});
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
catch (loopError) {
|
|
390
|
+
console.warn('Error during loop extraction:', loopError);
|
|
391
|
+
continue;
|
|
376
392
|
}
|
|
377
393
|
}
|
|
378
394
|
progressCallback({ progress: (index + 1) / numberOfPlanes });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cornerstonejs/polymorphic-segmentation",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.22.1",
|
|
4
4
|
"description": "Polymorphic Segmentation utility for Cornerstone3D",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist"
|
|
@@ -54,9 +54,9 @@
|
|
|
54
54
|
"@icr/polyseg-wasm": "0.4.0"
|
|
55
55
|
},
|
|
56
56
|
"peerDependencies": {
|
|
57
|
-
"@cornerstonejs/core": "^3.
|
|
58
|
-
"@cornerstonejs/tools": "^3.
|
|
57
|
+
"@cornerstonejs/core": "^3.22.1",
|
|
58
|
+
"@cornerstonejs/tools": "^3.22.1",
|
|
59
59
|
"@kitware/vtk.js": "32.12.1"
|
|
60
60
|
},
|
|
61
|
-
"gitHead": "
|
|
61
|
+
"gitHead": "23da62631a3c12ea7c677d89f01c12f99f2b9691"
|
|
62
62
|
}
|