-
-
Notifications
You must be signed in to change notification settings - Fork 909
Description
Search before asking
- I have searched the X-AnyLabeling issues and found no similar feature requests.
Description
Currently, X-AnyLabeling has excellent boundary clipping functionality for rectangle shapes - when a rectangle's points go
outside the image boundaries, the software automatically calculates and adjusts them to stay within bounds. However, this
same functionality is missing for rotation shapes, which can lead to inconsistent user experience.
🔄 Background
The rectangle boundary clipping feature (implemented in clip_rectangle_to_pixmap() method) was previously added based on user
feedback and works perfectly. When drawing rectangles:
- If any corner goes outside image bounds, it's automatically clipped to the edge
- The rectangle maintains its aspect ratio as much as possible
- Users get a smooth, predictable experience
Rotation shapes currently lack this same boundary management, making them behave differently from other shape types.
🎯 Proposed Feature
Implement automatic boundary clipping for rotation shapes similar to the existing rectangle functionality, ensuring that:
- When rotation shape vertices go outside image boundaries, they are automatically adjusted
- The rotation angle and proportions are preserved as much as possible
- The shape remains fully contained within the image bounds
🔍 Technical Analysis
Current Rectangle Implementation (✅ Working)
Location: anylabeling/views/labeling/widgets/canvas.py:273-315
def clip_rectangle_to_pixmap(self, shape):
"""Clip rectangle shape to pixmap boundaries"""
if self.pixmap is None or shape.shape_type != "rectangle":
return True
w, h = self.pixmap.width(), self.pixmap.height()
points = shape.points
# Calculate bounds and clip to [0, w] and [0, h]
x_coords = [p.x() for p in points]
y_coords = [p.y() for p in points]
min_x, max_x = min(x_coords), max(x_coords)
min_y, max_y = min(y_coords), max(y_coords)
# Clipping logic...
Called from: canvas.py:1992 when finishing rectangle drawing.
Current Rotation Implementation (❌ Missing Boundary Check)
Location: anylabeling/views/labeling/widgets/canvas.py:1097-1115
if shape.shape_type == "rotation":
sindex = (index + 2) % 4
# Get the other 3 points after transformed
p2, p3, p4 = self.get_adjoint_points(
shape.direction, shape[sindex], pos, index
)
# NOTE: No boundary clipping logic here
Rotation Shape Structure
- Rotation shapes use 4 points representing the corners of a rotated rectangle
- They store a direction property for the rotation angle
- Points are stored in shape.points[0] through shape.points[3]
💡 Suggested Implementation
- Create clip_rotation_to_pixmap() method
def clip_rotation_to_pixmap(self, shape):
"""Clip rotation shape to pixmap boundaries"""
if self.pixmap is None or shape.shape_type != "rotation":
return True
w, h = self.pixmap.width(), self.pixmap.height()
points = shape.points
if len(points) != 4:
return True
# Check if any point is out of bounds
out_of_bounds = False
for point in points:
if point.x() < 0 or point.x() > w or point.y() < 0 or point.y() > h:
out_of_bounds = True
break
if not out_of_bounds:
return True
# Calculate center and adjust
center_x = sum(p.x() for p in points) / 4
center_y = sum(p.y() for p in points) / 4
# Clip each point to bounds while preserving rotation
clipped_points = []
for point in points:
clipped_x = max(0, min(w, point.x()))
clipped_y = max(0, min(h, point.y()))
clipped_points.append(QtCore.QPointF(clipped_x, clipped_y))
# Update shape points
for i, clipped_point in enumerate(clipped_points):
shape.points[i] = clipped_point
return True
- Add boundary check in mouse release event
Modify canvas.py:1991-1997 to include rotation shapes:
if self.current.shape_type == "rectangle":
if not self.clip_rectangle_to_pixmap(self.current):
self.current = None
# ... cleanup code
elif self.current.shape_type == "rotation":
if not self.clip_rotation_to_pixmap(self.current):
self.current = None
# ... similar cleanup code
Use case
No response
Additional
No response
Are you willing to submit a PR?
- Yes I'd like to help by submitting a PR!