Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(splineSegROI): fix for CCW splines #1420

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion packages/tools/examples/splineContourSegmentationTools/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,19 @@ createInfoSection(content, { ordered: true })
'Notice that each segment index has a different color assigned to it'
)
.addInstruction('Change the style for the segmentation')
.addInstruction('Confirm the style is applied properly');
.addInstruction('Confirm the style is applied properly')
.addInstruction('You can draw overlapping splines to:')
.openNestedSection()
.addInstruction(
'Merge both splines when the first point of the second spline is inside the first spline'
)
.addInstruction(
'Subctract the second spline from the first spline when the first point of the second spline is outside the first spline'
)
.closeNestedSection()
.addInstruction(
'The resulting contour is converted to freehand ROI when splines are merged/subtracted'
);

function updateInputsForCurrentSegmentation() {
// We can use any toolGroupId because they are all configured in the same way
Expand Down
3 changes: 2 additions & 1 deletion packages/tools/src/tools/annotation/SplineROITool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -720,7 +720,8 @@ class SplineROITool extends ContourSegmentationBaseTool {
closed: data.contour.closed,
targetWindingDirection: ContourWindingDirection.Clockwise,
},
viewport
viewport,
{ updateWindingDirection: data.contour.closed }
);
});

Expand Down
4 changes: 4 additions & 0 deletions packages/tools/src/tools/base/ContourBaseTool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,9 @@ abstract class ContourBaseTool extends AnnotationTool {
transforms: {
canvasToWorld: (point: Types.Point2) => Types.Point3;
worldToCanvas: (point: Types.Point3) => Types.Point2;
},
options?: {
updateWindingDirection?: boolean;
}
) {
const decimateConfig = this.configuration?.decimate || {};
Expand All @@ -229,6 +232,7 @@ abstract class ContourBaseTool extends AnnotationTool {
enabled: !!decimateConfig.enabled,
epsilon: decimateConfig.epsilon,
},
updateWindingDirection: options?.updateWindingDirection,
});
}

Expand Down
40 changes: 22 additions & 18 deletions packages/tools/src/utilities/contours/updateContourPolyline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ export default function updateContourPolyline(
worldToCanvas: (point: Types.Point3) => Types.Point2;
},
options?: {
updateWindingDirection?: boolean;
decimate?: {
enabled?: boolean;
epsilon?: number;
Expand All @@ -55,8 +56,7 @@ export default function updateContourPolyline(
let { closed } = polylineData;
const numPoints = polyline.length;
const polylineWorldPoints = new Array(numPoints);
const currentPolylineWindingDirection =
math.polyline.getWindingDirection(polyline);
let windingDirection = math.polyline.getWindingDirection(polyline);
const parentAnnotation = getParentAnnotation(annotation) as ContourAnnotation;

if (closed === undefined) {
Expand All @@ -75,28 +75,32 @@ export default function updateContourPolyline(
closed = currentClosedState;
}

// It must be in the opposite direction if it is a child annotation (hole)
let windingDirection = parentAnnotation
? parentAnnotation.data.contour.windingDirection * -1
: targetWindingDirection;
if (options?.updateWindingDirection !== false) {
// It must be in the opposite direction if it is a child annotation (hole)
let updatedWindingDirection = parentAnnotation
? parentAnnotation.data.contour.windingDirection * -1
: targetWindingDirection;

if (windingDirection === undefined) {
windingDirection = currentPolylineWindingDirection;
}
if (updatedWindingDirection === undefined) {
updatedWindingDirection = windingDirection;
}

if (windingDirection !== currentPolylineWindingDirection) {
polyline.reverse();
}
if (updatedWindingDirection !== windingDirection) {
polyline.reverse();
}

const handlePoints = data.handles.points.map((p) => worldToCanvas(p));
const handlePoints = data.handles.points.map((p) => worldToCanvas(p));

if (handlePoints.length > 2) {
const currentHandlesWindingDirection =
math.polyline.getWindingDirection(handlePoints);
if (handlePoints.length > 2) {
const currentHandlesWindingDirection =
math.polyline.getWindingDirection(handlePoints);

if (currentHandlesWindingDirection !== windingDirection) {
data.handles.points.reverse();
if (currentHandlesWindingDirection !== updatedWindingDirection) {
data.handles.points.reverse();
}
}

windingDirection = updatedWindingDirection;
}

for (let i = 0; i < numPoints; i++) {
Expand Down