@cornerstonejs/polymorphic-segmentation 3.22.0 → 3.22.2

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.
@@ -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;
@@ -1 +1 @@
1
- export declare const version = "3.22.0";
1
+ export declare const version = "3.22.2";
@@ -1 +1 @@
1
- export const version = '3.22.0';
1
+ export const version = '3.22.2';
@@ -348,7 +348,7 @@ const polySegConverters = {
348
348
  continue;
349
349
  }
350
350
  surfacePolyData.getPoints().setData(points, 3);
351
- surfacePolyData.getPolys().setData(polys, 3);
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
- const loopOutput = loopExtraction.getOutputData();
369
- if (polyData) {
370
- polyDataResults.set(segmentIndex, {
371
- points: loopOutput.getPoints().getData(),
372
- lines: loopOutput.getLines().getData(),
373
- numberOfCells: loopOutput.getLines().getNumberOfCells(),
374
- segmentIndex,
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.22.0",
3
+ "version": "3.22.2",
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.22.0",
58
- "@cornerstonejs/tools": "^3.22.0",
57
+ "@cornerstonejs/core": "^3.22.2",
58
+ "@cornerstonejs/tools": "^3.22.2",
59
59
  "@kitware/vtk.js": "32.12.1"
60
60
  },
61
- "gitHead": "eae87d19be6d8bcdb00fa14fc747ab61ede54e1e"
61
+ "gitHead": "3d92fc6b7bb0483ba2a648a3207e3d29697690f0"
62
62
  }