44 convertMapperToNotSharedMapper ,
55 volumeLoader ,
66 eventTarget ,
7+ createVolumeActor ,
78 type Types ,
89} from '@cornerstonejs/core' ;
910import { Events , SegmentationRepresentations } from '../../../enums' ;
@@ -112,14 +113,6 @@ export async function addVolumesAsIndependentComponents({
112113
113114 viewport . removeActors ( [ uid ] ) ;
114115 const oldMapper = actor . getMapper ( ) ;
115- // convertMapperToNotSharedMapper reuses the old mapper's vtkImageData and
116- // replaces its point-data scalars with a CPU array, which this function then
117- // rewrites as a 2-component (base + seg) array. The shared streaming mapper
118- // renders from the GPU texture and misconfigures its shader if that injected
119- // array is still active, so capture the original scalars (usually none) to
120- // undo the mutation on restore.
121- const sharedImageData = ( oldMapper as vtkVolumeMapper ) . getInputData ( ) ;
122- const originalScalars = sharedImageData . getPointData ( ) . getScalars ( ) ?? null ;
123116 const mapper = convertMapperToNotSharedMapper ( oldMapper as vtkVolumeMapper ) ;
124117 actor . setMapper ( mapper ) ;
125118
@@ -144,29 +137,9 @@ export async function addVolumesAsIndependentComponents({
144137 . getIndependentComponents ( ) ;
145138 actor . getProperty ( ) . setIndependentComponents ( true ) ;
146139
147- // While the segmentation is mounted, setLabelmapColorAndOpacity treats this
148- // combined actor as the labelmap actor and enables the label-outline shader
149- // path on its property. Capture the pre-mount outline state so the restore
150- // can undo it - otherwise the plain base volume keeps rendering through the
151- // label-outline shader after the representation is removed.
152- const oldUseLabelOutline = actor . getProperty ( ) . getUseLabelOutline ( ) ;
153- // @ts -ignore - fix type in vtk
154- const oldLabelOutlineOpacity = actor . getProperty ( ) . getLabelOutlineOpacity ( ) ;
155- const oldLabelOutlineThickness = actor
156- . getProperty ( )
157- . getLabelOutlineThickness ( ) ;
158-
159- // Reuse the representationUID computed by the render plan (which includes
160- // the labelmapId suffix). The plan's reconcile step compares actor UIDs
161- // against that format; a mismatch makes it tear down this combined actor —
162- // which is also the viewport's base volume actor — on the next render.
163- const representationUID =
164- ( volumeInputArray [ 0 ] . representationUID as string ) ??
165- `${ segmentationId } -${ SegmentationRepresentations . Labelmap } ` ;
166-
167140 viewport . addActor ( {
168141 ...defaultActor ,
169- representationUID,
142+ representationUID : ` ${ segmentationId } - ${ SegmentationRepresentations . Labelmap } ` ,
170143 } ) ;
171144
172145 internalCache . set ( uid , {
@@ -182,7 +155,7 @@ export async function addVolumesAsIndependentComponents({
182155
183156 function onSegmentationDataModified ( evt ) {
184157 // update the second component of the array with the new segmentation data
185- const { segmentationId, modifiedSlicesToUse } = evt . detail ;
158+ const { segmentationId } = evt . detail ;
186159 const { representationData } = getSegmentation ( segmentationId ) ;
187160 const { volumeId : segVolumeId } =
188161 representationData . Labelmap as LabelmapSegmentationDataVolume ;
@@ -196,37 +169,24 @@ export async function addVolumesAsIndependentComponents({
196169
197170 const imageData = mapper . getInputData ( ) ;
198171 const array = imageData . getPointData ( ) . getArray ( 0 ) ;
199- const combinedData = array . getData ( ) ;
172+ const baseData = array . getData ( ) ;
200173 const newComp = 2 ;
201174 const dims = segImageData . getDimensions ( ) ;
202- const sliceSize = dims [ 0 ] * dims [ 1 ] ;
203175
204- // Brush strokes report which slices they touched; merging only those
205- // keeps the CPU cost proportional to the edit instead of the volume.
206- const slices : number [ ] = modifiedSlicesToUse ?. length
207- ? modifiedSlicesToUse
208- : Array . from ( { length : dims [ 2 ] } , ( _ , i ) => i ) ;
176+ const slices = Array . from ( { length : dims [ 2 ] } , ( _ , i ) => i ) ;
209177
210178 for ( const z of slices ) {
211- const sliceStart = z * sliceSize ;
212- const sliceImage = cache . getImage ( segmentationVolume . imageIds ?. [ z ] ) ;
213- const sliceData = sliceImage ?. voxelManager ?. getScalarData ?.( ) ;
214-
215- if ( sliceData ?. length === sliceSize ) {
216- for ( let i = 0 ; i < sliceSize ; ++ i ) {
217- combinedData [ ( sliceStart + i ) * newComp + 1 ] = sliceData [ i ] ;
218- }
219- } else {
220- for ( let i = 0 ; i < sliceSize ; ++ i ) {
221- const iTuple = sliceStart + i ;
222- combinedData [ iTuple * newComp + 1 ] = segVoxelManager . getAtIndex (
179+ for ( let y = 0 ; y < dims [ 1 ] ; ++ y ) {
180+ for ( let x = 0 ; x < dims [ 0 ] ; ++ x ) {
181+ const iTuple = x + dims [ 0 ] * ( y + dims [ 1 ] * z ) ;
182+ baseData [ iTuple * newComp + 1 ] = segVoxelManager . getAtIndex (
223183 iTuple
224184 ) as number ;
225185 }
226186 }
227187 }
228188
229- array . setData ( combinedData ) ;
189+ array . setData ( baseData ) ;
230190
231191 imageData . modified ( ) ;
232192 viewport . render ( ) ;
@@ -243,10 +203,7 @@ export async function addVolumesAsIndependentComponents({
243203 return ;
244204 }
245205
246- // The data-modified handler was registered debounced; the plain
247- // removeEventListener would leave the debounce wrapper attached forever,
248- // still merging into this detached imageData on every edit.
249- eventTarget . removeEventListenerDebounced (
206+ eventTarget . removeEventListener (
250207 Events . SEGMENTATION_DATA_MODIFIED ,
251208 onSegmentationDataModified
252209 ) ;
@@ -269,25 +226,11 @@ export async function addVolumesAsIndependentComponents({
269226
270227 // Restore the original actor and add it back to the viewport.
271228 actor . setMapper ( oldMapper ) ;
272-
273- const pointData = sharedImageData . getPointData ( ) ;
274-
275- if ( originalScalars ) {
276- pointData . setScalars ( originalScalars ) ;
277- } else {
278- pointData . removeArray ( 'Pixels' ) ;
279- }
280- sharedImageData . modified ( ) ;
281-
282229 actor . getProperty ( ) . setColorMixPreset ( oldColorMixPreset ) ;
283230 actor
284231 . getProperty ( )
285232 . setForceNearestInterpolation ( 1 , oldForceNearestInterpolation ) ;
286233 actor . getProperty ( ) . setIndependentComponents ( oldIndependentComponents ) ;
287- actor . getProperty ( ) . setUseLabelOutline ( oldUseLabelOutline ) ;
288- // @ts -ignore - fix type in vtk
289- actor . getProperty ( ) . setLabelOutlineOpacity ( oldLabelOutlineOpacity ) ;
290- actor . getProperty ( ) . setLabelOutlineThickness ( oldLabelOutlineThickness ) ;
291234
292235 viewport . addActor ( {
293236 ...defaultActor ,
0 commit comments