Refine freehand exclusion polygons

Store freehand paths as closed polygons with thin outlines and fill the interior when masking, so free-drawn shapes behave like custom rectangles.
This commit is contained in:
lm
2025-10-17 17:11:18 +02:00
parent f678c403b7
commit 464855f365
2 changed files with 25 additions and 21 deletions
+16 -10
View File
@@ -14,7 +14,6 @@ class ExclusionMixin:
y = max(0, min(self.preview_img.height - 1, int(event.y)))
if mode == "free":
self._current_stroke = [(x, y)]
width = int(getattr(self, "free_draw_width", 14))
preview_id = getattr(self, "_stroke_preview_id", None)
if preview_id:
try:
@@ -27,15 +26,13 @@ class ExclusionMixin:
x,
y,
fill="yellow",
width=width,
width=2,
smooth=True,
capstyle="round",
joinstyle="round",
)
self._rubber_start = None
return
x = max(0, min(self.preview_img.width - 1, int(event.x)))
y = max(0, min(self.preview_img.height - 1, int(event.y)))
self._rubber_start = (x, y)
if self._rubber_id:
try:
@@ -70,13 +67,12 @@ class ExclusionMixin:
mode = getattr(self, "exclude_mode", "rect")
if mode == "free":
stroke = getattr(self, "_current_stroke", None)
if stroke and len(stroke) > 1:
cleaned = self._compress_stroke(stroke)
if len(cleaned) > 1:
if stroke and len(stroke) > 2:
polygon = self._close_polygon(self._compress_stroke(stroke))
if len(polygon) >= 3:
shape = {
"kind": "stroke",
"points": cleaned,
"width": int(getattr(self, "free_draw_width", 14)),
"kind": "polygon",
"points": polygon,
}
self.exclude_shapes.append(shape)
stamper = getattr(self, "_stamp_shape_on_mask", None)
@@ -190,5 +186,15 @@ class ExclusionMixin:
compressed.append(point)
return compressed
@staticmethod
def _close_polygon(points: list[tuple[int, int]]) -> list[tuple[int, int]]:
"""Ensure the polygon is closed by repeating the start if necessary."""
if len(points) < 3:
return points
closed = list(points)
if closed[0] != closed[-1]:
closed.append(closed[0])
return closed
__all__ = ["ExclusionMixin"]