copper3d 3.4.4 → 3.4.5

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.
@@ -35,10 +35,18 @@ export interface ContourBBox {
35
35
  /** A single polygon's vertices in voxel-space coordinates. */
36
36
  export type ContourPolygon = ReadonlyArray<readonly [number, number]>;
37
37
  /**
38
- * Emit all per-cell polygons covering the voxels where `labels === targetLabel`.
38
+ * Emit polygons covering the voxels where `labels === targetLabel`.
39
39
  * Pure geometry function — no Canvas dependency. Consumers can build a Path2D
40
40
  * (see {@link extractLabelContours}) or walk the vertex arrays directly
41
41
  * (tests, export, stroke rendering).
42
+ *
43
+ * Boundary cells (marching-squares cases 1–14) emit their cut polygon as
44
+ * usual. Solid interior (case 15) is **coalesced into horizontal run-length
45
+ * rectangles** instead of one unit square per cell, collapsing the subpath
46
+ * count from O(area) to ≈ O(perimeter + rows). The filled region is
47
+ * pixel-identical (contiguous full-cell squares tile exactly into a rectangle
48
+ * with the same TL→TR→BR→BL winding), which is what keeps slice-scrubbing
49
+ * fast on large masks without changing the rendered silhouette.
42
50
  */
43
51
  export declare function extractLabelPolygons(labels: Uint8Array, width: number, height: number, targetLabel: number, stride?: number, channelOffset?: number, bbox?: ContourBBox): ContourPolygon[];
44
52
  /**
@@ -60,10 +60,18 @@ const CELL_POLYGONS = [
60
60
  /* 15 (full) */ [[[0, 0], [1, 0], [1, 1], [0, 1]]],
61
61
  ];
62
62
  /**
63
- * Emit all per-cell polygons covering the voxels where `labels === targetLabel`.
63
+ * Emit polygons covering the voxels where `labels === targetLabel`.
64
64
  * Pure geometry function — no Canvas dependency. Consumers can build a Path2D
65
65
  * (see {@link extractLabelContours}) or walk the vertex arrays directly
66
66
  * (tests, export, stroke rendering).
67
+ *
68
+ * Boundary cells (marching-squares cases 1–14) emit their cut polygon as
69
+ * usual. Solid interior (case 15) is **coalesced into horizontal run-length
70
+ * rectangles** instead of one unit square per cell, collapsing the subpath
71
+ * count from O(area) to ≈ O(perimeter + rows). The filled region is
72
+ * pixel-identical (contiguous full-cell squares tile exactly into a rectangle
73
+ * with the same TL→TR→BR→BL winding), which is what keeps slice-scrubbing
74
+ * fast on large masks without changing the rendered silhouette.
67
75
  */
68
76
  export function extractLabelPolygons(labels, width, height, targetLabel, stride = 1, channelOffset = 0, bbox) {
69
77
  var _a, _b, _c, _d;
@@ -85,7 +93,25 @@ export function extractLabelPolygons(labels, width, height, targetLabel, stride
85
93
  // map to voxel-square CENTERS in render space. Voxel (i, j) occupies
86
94
  // render square [i, i+1] × [j, j+1]; its center is (i+0.5, j+0.5).
87
95
  const SHIFT = 0.5;
96
+ // Emit a single rectangle covering a contiguous run of full (code 15)
97
+ // cells [runStart .. runEnd] on row j. A full cell i covers render square
98
+ // [i+0.5, i+1.5] × [j+0.5, j+1.5]; consecutive full cells tile perfectly,
99
+ // so the run is pixel-identical to the per-cell squares it replaces.
100
+ // Vertices use the same TL→TR→BR→BL (CCW screen-space) winding as the
101
+ // case-15 unit square, so the nonzero fill matches at shared edges.
102
+ const pushFullRun = (runStart, runEnd, j) => {
103
+ const x0 = runStart + SHIFT;
104
+ const x1 = runEnd + 1 + SHIFT;
105
+ const y0 = j + SHIFT;
106
+ const y1 = j + 1 + SHIFT;
107
+ out.push([[x0, y0], [x1, y0], [x1, y1], [x0, y1]]);
108
+ };
88
109
  for (let j = j0; j < j1; j++) {
110
+ // Index where the current contiguous run of full (code 15) cells began,
111
+ // or -1 when no run is open. Coalescing the solid interior into row runs
112
+ // drops the per-cell square count from O(area) to O(rows + perimeter),
113
+ // which is what keeps fast slice-scrubbing smooth on large masks.
114
+ let runStart = -1;
89
115
  for (let i = i0; i < i1; i++) {
90
116
  const tl = sample(i, j);
91
117
  const tr = sample(i + 1, j);
@@ -95,6 +121,17 @@ export function extractLabelPolygons(labels, width, height, targetLabel, stride
95
121
  (tr ? 4 : 0) |
96
122
  (br ? 2 : 0) |
97
123
  (bl ? 1 : 0);
124
+ if (code === 15) {
125
+ // Extend (or open) the current full-cell run; defer emission.
126
+ if (runStart === -1)
127
+ runStart = i;
128
+ continue;
129
+ }
130
+ // Non-full cell ends any open run — flush it as one rectangle.
131
+ if (runStart !== -1) {
132
+ pushFullRun(runStart, i - 1, j);
133
+ runStart = -1;
134
+ }
98
135
  if (code === 0)
99
136
  continue;
100
137
  const polygons = CELL_POLYGONS[code];
@@ -107,6 +144,10 @@ export function extractLabelPolygons(labels, width, height, targetLabel, stride
107
144
  out.push(abs);
108
145
  }
109
146
  }
147
+ // Flush a run that reached the end of the row (last visited cell is i1-1).
148
+ if (runStart !== -1) {
149
+ pushFullRun(runStart, i1 - 1, j);
150
+ }
110
151
  }
111
152
  return out;
112
153
  }
@@ -1 +1 @@
1
- {"version":3,"file":"MarchingSquares.js","sourceRoot":"","sources":["../../../../src/Utils/segmentation/core/MarchingSquares.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"MarchingSquares.js","sourceRoot":"","sources":["../../../../src/Utils/segmentation/core/MarchingSquares.ts"],"names":[],"mappings":"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"}
@@ -72153,10 +72153,18 @@ const CELL_POLYGONS = [
72153
72153
  /* 15 (full) */ [[[0, 0], [1, 0], [1, 1], [0, 1]]],
72154
72154
  ];
72155
72155
  /**
72156
- * Emit all per-cell polygons covering the voxels where `labels === targetLabel`.
72156
+ * Emit polygons covering the voxels where `labels === targetLabel`.
72157
72157
  * Pure geometry function — no Canvas dependency. Consumers can build a Path2D
72158
72158
  * (see {@link extractLabelContours}) or walk the vertex arrays directly
72159
72159
  * (tests, export, stroke rendering).
72160
+ *
72161
+ * Boundary cells (marching-squares cases 1–14) emit their cut polygon as
72162
+ * usual. Solid interior (case 15) is **coalesced into horizontal run-length
72163
+ * rectangles** instead of one unit square per cell, collapsing the subpath
72164
+ * count from O(area) to ≈ O(perimeter + rows). The filled region is
72165
+ * pixel-identical (contiguous full-cell squares tile exactly into a rectangle
72166
+ * with the same TL→TR→BR→BL winding), which is what keeps slice-scrubbing
72167
+ * fast on large masks without changing the rendered silhouette.
72160
72168
  */
72161
72169
  function extractLabelPolygons(labels, width, height, targetLabel, stride = 1, channelOffset = 0, bbox) {
72162
72170
  var _a, _b, _c, _d;
@@ -72178,7 +72186,25 @@ function extractLabelPolygons(labels, width, height, targetLabel, stride = 1, ch
72178
72186
  // map to voxel-square CENTERS in render space. Voxel (i, j) occupies
72179
72187
  // render square [i, i+1] × [j, j+1]; its center is (i+0.5, j+0.5).
72180
72188
  const SHIFT = 0.5;
72189
+ // Emit a single rectangle covering a contiguous run of full (code 15)
72190
+ // cells [runStart .. runEnd] on row j. A full cell i covers render square
72191
+ // [i+0.5, i+1.5] × [j+0.5, j+1.5]; consecutive full cells tile perfectly,
72192
+ // so the run is pixel-identical to the per-cell squares it replaces.
72193
+ // Vertices use the same TL→TR→BR→BL (CCW screen-space) winding as the
72194
+ // case-15 unit square, so the nonzero fill matches at shared edges.
72195
+ const pushFullRun = (runStart, runEnd, j) => {
72196
+ const x0 = runStart + SHIFT;
72197
+ const x1 = runEnd + 1 + SHIFT;
72198
+ const y0 = j + SHIFT;
72199
+ const y1 = j + 1 + SHIFT;
72200
+ out.push([[x0, y0], [x1, y0], [x1, y1], [x0, y1]]);
72201
+ };
72181
72202
  for (let j = j0; j < j1; j++) {
72203
+ // Index where the current contiguous run of full (code 15) cells began,
72204
+ // or -1 when no run is open. Coalescing the solid interior into row runs
72205
+ // drops the per-cell square count from O(area) to O(rows + perimeter),
72206
+ // which is what keeps fast slice-scrubbing smooth on large masks.
72207
+ let runStart = -1;
72182
72208
  for (let i = i0; i < i1; i++) {
72183
72209
  const tl = sample(i, j);
72184
72210
  const tr = sample(i + 1, j);
@@ -72188,6 +72214,17 @@ function extractLabelPolygons(labels, width, height, targetLabel, stride = 1, ch
72188
72214
  (tr ? 4 : 0) |
72189
72215
  (br ? 2 : 0) |
72190
72216
  (bl ? 1 : 0);
72217
+ if (code === 15) {
72218
+ // Extend (or open) the current full-cell run; defer emission.
72219
+ if (runStart === -1)
72220
+ runStart = i;
72221
+ continue;
72222
+ }
72223
+ // Non-full cell ends any open run — flush it as one rectangle.
72224
+ if (runStart !== -1) {
72225
+ pushFullRun(runStart, i - 1, j);
72226
+ runStart = -1;
72227
+ }
72191
72228
  if (code === 0)
72192
72229
  continue;
72193
72230
  const polygons = CELL_POLYGONS[code];
@@ -72200,6 +72237,10 @@ function extractLabelPolygons(labels, width, height, targetLabel, stride = 1, ch
72200
72237
  out.push(abs);
72201
72238
  }
72202
72239
  }
72240
+ // Flush a run that reached the end of the row (last visited cell is i1-1).
72241
+ if (runStart !== -1) {
72242
+ pushFullRun(runStart, i1 - 1, j);
72243
+ }
72203
72244
  }
72204
72245
  return out;
72205
72246
  }
@@ -79409,7 +79450,7 @@ function evaluateElement(element, weights) {
79409
79450
  }
79410
79451
 
79411
79452
  // import * as kiwrious from "copper3d_plugin_heart_k";
79412
- const REVISION = "v3.4.4-beta";
79453
+ const REVISION = "v3.4.5-beta";
79413
79454
  console.log(`%cCopper3D Visualisation %cBeta:${REVISION}`, "padding: 3px;color:white; background:#023047", "padding: 3px;color:white; background:#f50a25");
79414
79455
 
79415
79456
  export { CHANNEL_COLORS, CHANNEL_HEX_COLORS, CameraViewPoint, Copper3dTrackballControls, GaussianSmoother, MeshNodeTool, NrrdTools, REVISION, addBoxHelper, addLabelToScene, configKiwriousHeart, convert3DPostoScreenPos, convertScreenPosto3DPos, copperMScene, copperMSceneRenderer, copperRenderer, copperRendererOnDemond, copperScene, copperSceneOnDemond, createTexture2D_NRRD, fullScreenListenner, kiwrious, loading, removeGuiFolderChilden, rgbaToCss, rgbaToHex, setHDRFilePath, throttle };
@@ -72161,10 +72161,18 @@ void main() {
72161
72161
  /* 15 (full) */ [[[0, 0], [1, 0], [1, 1], [0, 1]]],
72162
72162
  ];
72163
72163
  /**
72164
- * Emit all per-cell polygons covering the voxels where `labels === targetLabel`.
72164
+ * Emit polygons covering the voxels where `labels === targetLabel`.
72165
72165
  * Pure geometry function — no Canvas dependency. Consumers can build a Path2D
72166
72166
  * (see {@link extractLabelContours}) or walk the vertex arrays directly
72167
72167
  * (tests, export, stroke rendering).
72168
+ *
72169
+ * Boundary cells (marching-squares cases 1–14) emit their cut polygon as
72170
+ * usual. Solid interior (case 15) is **coalesced into horizontal run-length
72171
+ * rectangles** instead of one unit square per cell, collapsing the subpath
72172
+ * count from O(area) to ≈ O(perimeter + rows). The filled region is
72173
+ * pixel-identical (contiguous full-cell squares tile exactly into a rectangle
72174
+ * with the same TL→TR→BR→BL winding), which is what keeps slice-scrubbing
72175
+ * fast on large masks without changing the rendered silhouette.
72168
72176
  */
72169
72177
  function extractLabelPolygons(labels, width, height, targetLabel, stride = 1, channelOffset = 0, bbox) {
72170
72178
  var _a, _b, _c, _d;
@@ -72186,7 +72194,25 @@ void main() {
72186
72194
  // map to voxel-square CENTERS in render space. Voxel (i, j) occupies
72187
72195
  // render square [i, i+1] × [j, j+1]; its center is (i+0.5, j+0.5).
72188
72196
  const SHIFT = 0.5;
72197
+ // Emit a single rectangle covering a contiguous run of full (code 15)
72198
+ // cells [runStart .. runEnd] on row j. A full cell i covers render square
72199
+ // [i+0.5, i+1.5] × [j+0.5, j+1.5]; consecutive full cells tile perfectly,
72200
+ // so the run is pixel-identical to the per-cell squares it replaces.
72201
+ // Vertices use the same TL→TR→BR→BL (CCW screen-space) winding as the
72202
+ // case-15 unit square, so the nonzero fill matches at shared edges.
72203
+ const pushFullRun = (runStart, runEnd, j) => {
72204
+ const x0 = runStart + SHIFT;
72205
+ const x1 = runEnd + 1 + SHIFT;
72206
+ const y0 = j + SHIFT;
72207
+ const y1 = j + 1 + SHIFT;
72208
+ out.push([[x0, y0], [x1, y0], [x1, y1], [x0, y1]]);
72209
+ };
72189
72210
  for (let j = j0; j < j1; j++) {
72211
+ // Index where the current contiguous run of full (code 15) cells began,
72212
+ // or -1 when no run is open. Coalescing the solid interior into row runs
72213
+ // drops the per-cell square count from O(area) to O(rows + perimeter),
72214
+ // which is what keeps fast slice-scrubbing smooth on large masks.
72215
+ let runStart = -1;
72190
72216
  for (let i = i0; i < i1; i++) {
72191
72217
  const tl = sample(i, j);
72192
72218
  const tr = sample(i + 1, j);
@@ -72196,6 +72222,17 @@ void main() {
72196
72222
  (tr ? 4 : 0) |
72197
72223
  (br ? 2 : 0) |
72198
72224
  (bl ? 1 : 0);
72225
+ if (code === 15) {
72226
+ // Extend (or open) the current full-cell run; defer emission.
72227
+ if (runStart === -1)
72228
+ runStart = i;
72229
+ continue;
72230
+ }
72231
+ // Non-full cell ends any open run — flush it as one rectangle.
72232
+ if (runStart !== -1) {
72233
+ pushFullRun(runStart, i - 1, j);
72234
+ runStart = -1;
72235
+ }
72199
72236
  if (code === 0)
72200
72237
  continue;
72201
72238
  const polygons = CELL_POLYGONS[code];
@@ -72208,6 +72245,10 @@ void main() {
72208
72245
  out.push(abs);
72209
72246
  }
72210
72247
  }
72248
+ // Flush a run that reached the end of the row (last visited cell is i1-1).
72249
+ if (runStart !== -1) {
72250
+ pushFullRun(runStart, i1 - 1, j);
72251
+ }
72211
72252
  }
72212
72253
  return out;
72213
72254
  }
@@ -79417,7 +79458,7 @@ void main() {
79417
79458
  }
79418
79459
 
79419
79460
  // import * as kiwrious from "copper3d_plugin_heart_k";
79420
- const REVISION = "v3.4.4-beta";
79461
+ const REVISION = "v3.4.5-beta";
79421
79462
  console.log(`%cCopper3D Visualisation %cBeta:${REVISION}`, "padding: 3px;color:white; background:#023047", "padding: 3px;color:white; background:#f50a25");
79422
79463
 
79423
79464
  exports.CHANNEL_COLORS = CHANNEL_COLORS;
package/dist/index.d.ts CHANGED
@@ -25,6 +25,6 @@ import type { ToolMode, IAnnotationCallbacks } from "./Utils/segmentation/core/t
25
25
  import { CHANNEL_COLORS, CHANNEL_HEX_COLORS, rgbaToHex, rgbaToCss } from "./Utils/segmentation/core/index";
26
26
  import type { LayerId, ChannelValue } from "./Utils/segmentation/core/index";
27
27
  import "./css/style.css";
28
- export declare const REVISION = "v3.4.4-beta";
28
+ export declare const REVISION = "v3.4.5-beta";
29
29
  export { copperRenderer, copperRendererOnDemond, copperMSceneRenderer, setHDRFilePath, addLabelToScene, convert3DPostoScreenPos, convertScreenPosto3DPos, addBoxHelper, fullScreenListenner, configKiwriousHeart, copperScene, copperSceneOnDemond, copperMScene, CameraViewPoint, kiwrious, NrrdTools, loading, Copper3dTrackballControls, createTexture2D_NRRD, MeshNodeTool, throttle, removeGuiFolderChilden, CHANNEL_COLORS, CHANNEL_HEX_COLORS, rgbaToHex, rgbaToCss, GaussianSmoother, };
30
30
  export type { positionType, screenPosType, optsType, nrrdMeshesType, nrrdSliceType, SensorDecodedValue_kiwrious, SensorReadResult_kiwrious, HeartRateResult_kiwrious, loadingBarType, IPaintImage, exportPaintImageType, IOptVTKLoader, ICommXYZ, IGUIStates, IGuiParameterSettings, INrrdStates, NrrdState, GuiState, IGuiMeta, ToolMode, IAnnotationCallbacks, LayerId, ChannelValue, };
package/dist/index.js CHANGED
@@ -21,7 +21,7 @@ import { MeshNodeTool } from "./Utils/MeshNodeTool";
21
21
  import { removeGuiFolderChilden } from "./Utils/segmentation/coreTools/gui";
22
22
  import { CHANNEL_COLORS, CHANNEL_HEX_COLORS, rgbaToHex, rgbaToCss } from "./Utils/segmentation/core/index";
23
23
  import "./css/style.css";
24
- export const REVISION = "v3.4.4-beta";
24
+ export const REVISION = "v3.4.5-beta";
25
25
  console.log(`%cCopper3D Visualisation %cBeta:${REVISION}`, "padding: 3px;color:white; background:#023047", "padding: 3px;color:white; background:#f50a25");
26
26
  export { copperRenderer, copperRendererOnDemond, copperMSceneRenderer, setHDRFilePath, addLabelToScene, convert3DPostoScreenPos, convertScreenPosto3DPos, addBoxHelper, fullScreenListenner, configKiwriousHeart, copperScene, copperSceneOnDemond, copperMScene, CameraViewPoint, kiwrious, NrrdTools, loading, Copper3dTrackballControls, createTexture2D_NRRD, MeshNodeTool, throttle, removeGuiFolderChilden, CHANNEL_COLORS, CHANNEL_HEX_COLORS, rgbaToHex, rgbaToCss, GaussianSmoother, };
27
27
  //# sourceMappingURL=index.js.map
@@ -35,10 +35,18 @@ export interface ContourBBox {
35
35
  /** A single polygon's vertices in voxel-space coordinates. */
36
36
  export type ContourPolygon = ReadonlyArray<readonly [number, number]>;
37
37
  /**
38
- * Emit all per-cell polygons covering the voxels where `labels === targetLabel`.
38
+ * Emit polygons covering the voxels where `labels === targetLabel`.
39
39
  * Pure geometry function — no Canvas dependency. Consumers can build a Path2D
40
40
  * (see {@link extractLabelContours}) or walk the vertex arrays directly
41
41
  * (tests, export, stroke rendering).
42
+ *
43
+ * Boundary cells (marching-squares cases 1–14) emit their cut polygon as
44
+ * usual. Solid interior (case 15) is **coalesced into horizontal run-length
45
+ * rectangles** instead of one unit square per cell, collapsing the subpath
46
+ * count from O(area) to ≈ O(perimeter + rows). The filled region is
47
+ * pixel-identical (contiguous full-cell squares tile exactly into a rectangle
48
+ * with the same TL→TR→BR→BL winding), which is what keeps slice-scrubbing
49
+ * fast on large masks without changing the rendered silhouette.
42
50
  */
43
51
  export declare function extractLabelPolygons(labels: Uint8Array, width: number, height: number, targetLabel: number, stride?: number, channelOffset?: number, bbox?: ContourBBox): ContourPolygon[];
44
52
  /**
@@ -25,6 +25,6 @@ import type { ToolMode, IAnnotationCallbacks } from "./Utils/segmentation/core/t
25
25
  import { CHANNEL_COLORS, CHANNEL_HEX_COLORS, rgbaToHex, rgbaToCss } from "./Utils/segmentation/core/index";
26
26
  import type { LayerId, ChannelValue } from "./Utils/segmentation/core/index";
27
27
  import "./css/style.css";
28
- export declare const REVISION = "v3.4.4-beta";
28
+ export declare const REVISION = "v3.4.5-beta";
29
29
  export { copperRenderer, copperRendererOnDemond, copperMSceneRenderer, setHDRFilePath, addLabelToScene, convert3DPostoScreenPos, convertScreenPosto3DPos, addBoxHelper, fullScreenListenner, configKiwriousHeart, copperScene, copperSceneOnDemond, copperMScene, CameraViewPoint, kiwrious, NrrdTools, loading, Copper3dTrackballControls, createTexture2D_NRRD, MeshNodeTool, throttle, removeGuiFolderChilden, CHANNEL_COLORS, CHANNEL_HEX_COLORS, rgbaToHex, rgbaToCss, GaussianSmoother, };
30
30
  export type { positionType, screenPosType, optsType, nrrdMeshesType, nrrdSliceType, SensorDecodedValue_kiwrious, SensorReadResult_kiwrious, HeartRateResult_kiwrious, loadingBarType, IPaintImage, exportPaintImageType, IOptVTKLoader, ICommXYZ, IGUIStates, IGuiParameterSettings, INrrdStates, NrrdState, GuiState, IGuiMeta, ToolMode, IAnnotationCallbacks, LayerId, ChannelValue, };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "copper3d",
3
3
  "description": "A 3d visualisation package base on threejs provides multiple scenes and Nrrd image load funtion.",
4
- "version": "3.4.4",
4
+ "version": "3.4.5",
5
5
  "main": "dist/bundle.umd.js",
6
6
  "moudle": "dist/bundle.esm.js",
7
7
  "types": "dist/types/index.d.ts",