Skip to content

Commit 96aac36

Browse files
Remove annotations after operation
1 parent 604082e commit 96aac36

File tree

3 files changed

+82
-65
lines changed

3 files changed

+82
-65
lines changed

packages/tools/examples/logicalOperators/index.ts

Lines changed: 42 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -124,11 +124,12 @@ const contourToolsNames = [
124124
let selectedToolName = contourToolsNames[0];
125125

126126
const segmentIndices = [1, 2, 3, 4, 5];
127-
let sourceSegmentIndex = segmentIndices[0];
128-
let targetSegmentIndex = segmentIndices[1];
127+
let firstSegmentIndex = segmentIndices[0];
128+
let secondSegmentIndex = segmentIndices[1];
129+
let outputSegmentIndex = segmentIndices[0];
129130

130131
addDropdownToToolbar({
131-
labelText: 'Active segment',
132+
labelText: 'Drawing segment',
132133
options: { values: segmentIndices, defaultValue: segmentIndices[0] },
133134
onSelectedValueChange: (nameAsStringOrNumber) => {
134135
const segmentIndex = Number(nameAsStringOrNumber);
@@ -158,10 +159,10 @@ addDropdownToToolbar({
158159
});
159160

160161
addDropdownToToolbar({
161-
labelText: 'Source segment',
162+
labelText: 'First segment',
162163
options: { values: segmentIndices, defaultValue: segmentIndices[0] },
163164
onSelectedValueChange: (nameAsStringOrNumber) => {
164-
sourceSegmentIndex = Number(nameAsStringOrNumber);
165+
firstSegmentIndex = Number(nameAsStringOrNumber);
165166
},
166167
});
167168

@@ -189,55 +190,57 @@ addDropdownToToolbar({
189190
selectedOperation = LogicalOperation.Delete;
190191
break;
191192
}
192-
// Enable/disable the target segment dropdown based on operation
193-
const targetDropdown = document.getElementById(
194-
'targetSegmentIndex'
193+
// Enable/disable the second segment dropdown based on operation
194+
const secondDropdown = document.getElementById(
195+
'secondSegmentIndex'
195196
) as HTMLSelectElement | null;
196-
if (targetDropdown) {
197+
if (secondDropdown) {
197198
if (
198199
selectedOperation === LogicalOperation.Copy ||
199200
selectedOperation === LogicalOperation.Delete
200201
) {
201-
targetDropdown.disabled = true;
202+
secondDropdown.disabled = true;
202203
} else {
203-
targetDropdown.disabled = false;
204+
secondDropdown.disabled = false;
204205
}
205206
}
206-
// Enable/disable the "Apply operation and create new segment" button for Copy/Delete
207-
const applyAndCreateNewSegmentBtn = document.getElementById(
208-
'applyAndCreateNewSegment'
209-
) as HTMLButtonElement | null;
210-
if (applyAndCreateNewSegmentBtn) {
207+
208+
// Enable/disable the output segment dropdown based on operation
209+
const outputDropDown = document.getElementById(
210+
'outputSegmentIndex'
211+
) as HTMLSelectElement | null;
212+
if (outputDropDown) {
211213
if (selectedOperation === LogicalOperation.Delete) {
212-
applyAndCreateNewSegmentBtn.disabled = true;
214+
outputDropDown.disabled = true;
213215
} else {
214-
applyAndCreateNewSegmentBtn.disabled = false;
216+
outputDropDown.disabled = false;
215217
}
216218
}
217219
},
218220
});
219221

220222
addDropdownToToolbar({
221-
id: 'targetSegmentIndex',
222-
labelText: 'Target segment',
223+
id: 'secondSegmentIndex',
224+
labelText: 'Second segment',
223225
options: { values: segmentIndices, defaultValue: segmentIndices[1] },
224226
onSelectedValueChange: (nameAsStringOrNumber) => {
225-
targetSegmentIndex = Number(nameAsStringOrNumber);
227+
secondSegmentIndex = Number(nameAsStringOrNumber);
226228
},
227229
});
228230

229-
addButtonToToolbar({
230-
title: 'Apply operation',
231-
onClick: function () {
232-
performLogicalOperation(selectedOperation, false);
231+
addDropdownToToolbar({
232+
id: 'outputSegmentIndex',
233+
labelText: '= Output segment',
234+
options: { values: segmentIndices, defaultValue: segmentIndices[0] },
235+
onSelectedValueChange: (nameAsStringOrNumber) => {
236+
outputSegmentIndex = Number(nameAsStringOrNumber);
233237
},
234238
});
235239

236240
addButtonToToolbar({
237-
id: 'applyAndCreateNewSegment',
238-
title: 'Apply operation and create new segment',
241+
title: 'Apply operation',
239242
onClick: function () {
240-
performLogicalOperation(selectedOperation, true);
243+
performLogicalOperation(selectedOperation, false);
241244
},
242245
});
243246

@@ -262,16 +265,9 @@ function performLogicalOperation(
262265

263266
if (annotationUIDsMap) {
264267
const segmentIndexes = Array.from(annotationUIDsMap.keys());
265-
let newIndex = 0;
266-
if (createNew) {
267-
newIndex = Math.max(...segmentIndexes) + 1;
268-
} else {
269-
newIndex = targetSegmentIndex;
270-
}
271268
const operatorOptions = {
272269
segmentationId: activeSeg.segmentationId,
273-
label: 'Combined Addition',
274-
segmentIndex: newIndex,
270+
segmentIndex: outputSegmentIndex,
275271
color: 'rgb(50, 130, 162)',
276272
};
277273

@@ -280,14 +276,14 @@ function performLogicalOperation(
280276
copy(
281277
{
282278
segmentationId: activeSeg.segmentationId,
283-
segmentIndex: sourceSegmentIndex,
279+
segmentIndex: firstSegmentIndex,
284280
},
285281
operatorOptions
286282
);
287283
} else if (operation === LogicalOperation.Delete) {
288284
deleteOperation({
289285
segmentationId: activeSeg.segmentationId,
290-
segmentIndex: sourceSegmentIndex,
286+
segmentIndex: firstSegmentIndex,
291287
});
292288
}
293289
}
@@ -296,47 +292,47 @@ function performLogicalOperation(
296292
add(
297293
{
298294
segmentationId: activeSeg.segmentationId,
299-
segmentIndex: sourceSegmentIndex,
295+
segmentIndex: firstSegmentIndex,
300296
},
301297
{
302298
segmentationId: activeSeg.segmentationId,
303-
segmentIndex: targetSegmentIndex,
299+
segmentIndex: secondSegmentIndex,
304300
},
305301
operatorOptions
306302
);
307303
} else if (operation === LogicalOperation.Subtract) {
308304
subtract(
309305
{
310306
segmentationId: activeSeg.segmentationId,
311-
segmentIndex: sourceSegmentIndex,
307+
segmentIndex: firstSegmentIndex,
312308
},
313309
{
314310
segmentationId: activeSeg.segmentationId,
315-
segmentIndex: targetSegmentIndex,
311+
segmentIndex: secondSegmentIndex,
316312
},
317313
operatorOptions
318314
);
319315
} else if (operation === LogicalOperation.Intersect) {
320316
intersect(
321317
{
322318
segmentationId: activeSeg.segmentationId,
323-
segmentIndex: sourceSegmentIndex,
319+
segmentIndex: firstSegmentIndex,
324320
},
325321
{
326322
segmentationId: activeSeg.segmentationId,
327-
segmentIndex: targetSegmentIndex,
323+
segmentIndex: secondSegmentIndex,
328324
},
329325
operatorOptions
330326
);
331327
} else if (operation === LogicalOperation.XOR) {
332328
xor(
333329
{
334330
segmentationId: activeSeg.segmentationId,
335-
segmentIndex: sourceSegmentIndex,
331+
segmentIndex: firstSegmentIndex,
336332
},
337333
{
338334
segmentationId: activeSeg.segmentationId,
339-
segmentIndex: targetSegmentIndex,
335+
segmentIndex: secondSegmentIndex,
340336
},
341337
operatorOptions
342338
);

packages/tools/src/utilities/contourSegmentation/logicalOperators.ts

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
* - applyLogicalOperation: Internal function to apply a logical operation and update the segmentation
2121
*
2222
* Helper Functions:
23-
* - getViewReferenceFromAnnotation: Extracts view reference from annotation metadata
2423
* - getPolylinesInfoWorld: Gets world-space polylines and view references for a segment
2524
* - extractPolylinesInCanvasSpace: Converts world-space polylines to canvas space for two segments
2625
* - addSegmentInSegmentation: Adds a new segment to the segmentation object
@@ -175,6 +174,25 @@ function addSegmentInSegmentation(
175174
};
176175
}
177176

177+
/**
178+
* Removes all annotations for a given segment index from the segmentation.
179+
* This function iterates through the provided annotationUIDList,
180+
* retrieves each annotation, removes it from the state management,
181+
* and also removes the corresponding contour segmentation annotation.
182+
* After processing, it clears the annotationUIDList to avoid memory leaks or unintended reuse.
183+
* @param annotationUIDList
184+
*/
185+
function removeAnnotations(annotationUIDList: Set<string>) {
186+
annotationUIDList.forEach((annotationUID) => {
187+
const annotation = getAnnotation(annotationUID);
188+
removeAnnotation(annotationUID);
189+
removeContourSegmentationAnnotation(
190+
annotation as ContourSegmentationAnnotation
191+
);
192+
});
193+
annotationUIDList.clear(); // Clear the set after removal
194+
}
195+
178196
/**
179197
* Applies a logical operation (union, subtract, intersect, xor) between two segments,
180198
* converts the result back to world space, and updates the segmentation.
@@ -252,6 +270,18 @@ function applyLogicalOperation(
252270
if (!annotationUIDsMap) {
253271
return;
254272
}
273+
if (
274+
segment1.segmentationId === resultSegment.segmentationId &&
275+
segment1.segmentIndex === segmentIndex
276+
) {
277+
// If the segment being modified is the same as the result segment,
278+
// we need to remove the existing annotations for that segment
279+
// index before adding new ones.
280+
const existingAnnotationUIDs = annotationUIDsMap.get(segmentIndex);
281+
if (existingAnnotationUIDs) {
282+
removeAnnotations(existingAnnotationUIDs);
283+
}
284+
}
255285
// Add polylines to segmentation, passing viewReference for each
256286
addPolylinesToSegmentation(
257287
viewport,
@@ -367,11 +397,5 @@ export function deleteOperation(segment: SegmentInfo) {
367397
}
368398

369399
const annotationUIDList = annotationUIDsMap.get(segment.segmentIndex);
370-
annotationUIDList.forEach((annotationUID) => {
371-
const annotation = getAnnotation(annotationUID);
372-
removeAnnotation(annotationUID);
373-
removeContourSegmentationAnnotation(
374-
annotation as ContourSegmentationAnnotation
375-
);
376-
});
400+
removeAnnotations(annotationUIDList);
377401
}

packages/tools/src/utilities/contourSegmentation/polylineSubtract.ts

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,14 @@ export function subtractPolylineSets(
3737
polylineB.viewReference
3838
)
3939
) {
40-
continue; // Skip if view references are not equal
40+
// If viewReference does not match, keep the polyline for further checks
41+
newPolylines.push(currentPolyline);
42+
continue;
4143
}
42-
4344
if (
4445
arePolylinesIdentical(currentPolyline.polyline, polylineB.polyline)
4546
) {
47+
// Polyline is identical, so it is subtracted (not added to newPolylines)
4648
continue;
4749
}
4850
const intersection = checkIntersection(
@@ -66,15 +68,10 @@ export function subtractPolylineSets(
6668
}
6769
}
6870
} else {
69-
const cleaned = removeDuplicatePoints(
70-
cleanupPolylines([currentPolyline.polyline])[0]
71-
);
72-
if (cleaned.length >= 3) {
73-
newPolylines.push({
74-
polyline: cleaned,
75-
viewReference: currentPolyline.viewReference,
76-
});
77-
}
71+
newPolylines.push({
72+
polyline: currentPolyline.polyline,
73+
viewReference: currentPolyline.viewReference,
74+
});
7875
}
7976
}
8077
currentPolylines = newPolylines;

0 commit comments

Comments
 (0)