Skip to content

Commit 7f4e967

Browse files
committed
🐛 fix(canvas): align rotated-box docs and optimize keyboard rotation repaint (#1333)
1 parent 102eea2 commit 7f4e967

3 files changed

Lines changed: 22 additions & 24 deletions

File tree

anylabeling/views/labeling/widgets/canvas.py

Lines changed: 20 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
"""This module defines Canvas widget - the core component for drawing image labels"""
22

33
import math
4-
from copy import deepcopy
54
from PyQt6 import QtCore, QtGui, QtWidgets
65
from PyQt6.QtCore import Qt, QTimer
76
from PyQt6.QtGui import QWheelEvent
@@ -2039,33 +2038,29 @@ def rotate_point(self, p, center, theta):
20392038

20402039
def bounded_rotate_shapes(self, i, shape, theta):
20412040
"""Rotate shapes. Adjust position to be bounded by pixmap border"""
2042-
new_shape = deepcopy(shape)
20432041
if len(shape.points) == 2:
2044-
new_shape.points[0] = shape.points[0]
2045-
new_shape.points[1] = QtCore.QPointF(
2046-
(shape.points[0].x() + shape.points[1].x()) / 2,
2047-
shape.points[0].y(),
2048-
)
2049-
new_shape.points.append(shape.points[1])
2050-
new_shape.points.append(
2042+
p0 = shape.points[0]
2043+
p1 = shape.points[1]
2044+
shape.points = [
2045+
p0,
20512046
QtCore.QPointF(
2052-
shape.points[1].x(),
2053-
(shape.points[0].y() + shape.points[1].y()) / 2,
2054-
)
2055-
)
2047+
(p0.x() + p1.x()) / 2,
2048+
p0.y(),
2049+
),
2050+
p1,
2051+
QtCore.QPointF(p1.x(), (p0.y() + p1.y()) / 2),
2052+
]
20562053
center = QtCore.QPointF(
2057-
(new_shape.points[0].x() + new_shape.points[2].x()) / 2,
2058-
(new_shape.points[0].y() + new_shape.points[2].y()) / 2,
2054+
(shape.points[0].x() + shape.points[2].x()) / 2,
2055+
(shape.points[0].y() + shape.points[2].y()) / 2,
20592056
)
2060-
for j, p in enumerate(new_shape.points):
2057+
for j, p in enumerate(shape.points):
20612058
pos = self.rotate_point(p, center, theta)
20622059
# TODO: Reserved for now
20632060
# if self.out_off_pixmap(pos):
20642061
# return False # No need to rotate
2065-
new_shape.points[j] = pos
2066-
new_shape.direction = (new_shape.direction - theta) % (2 * math.pi)
2067-
self.selected_shapes[i].points = new_shape.points
2068-
self.selected_shapes[i].direction = new_shape.direction
2062+
shape.points[j] = pos
2063+
shape.direction = (shape.direction - theta) % (2 * math.pi)
20692064
return True
20702065

20712066
def deselect_shape(self):
@@ -3369,11 +3364,14 @@ def move_by_keyboard(self, offset):
33693364
def rotate_by_keyboard(self, theta):
33703365
"""Rotate selected shapes by an theta (using keyboard)"""
33713366
if self.selected_shapes:
3367+
rotating_shape = False
33723368
for i, shape in enumerate(self.selected_shapes):
33733369
if shape._shape_type == "rotation":
33743370
self.bounded_rotate_shapes(i, shape, theta)
3375-
self.repaint()
3376-
self.rotating_shape = True
3371+
rotating_shape = True
3372+
if rotating_shape:
3373+
self.repaint()
3374+
self.rotating_shape = True
33773375

33783376
# QT Overload
33793377
def keyPressEvent(self, ev):

docs/en/user_guide.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ For detailed field definitions, see [`shape.py`](../../anylabeling/views/labelin
192192
X-AnyLabeling supports creating the following types of shapes:
193193

194194
- **Rectangle** (`R`): Click and drag to define opposite corners, or click once for the first corner and again for the second.
195-
- **Rotated Rectangle** (`O`): Click to set the first point, click again for the second point defining one side, then move the cursor to set the height and click a third time.
195+
- **Rotated Rectangle** (`O`): Click once to set the first corner, move the cursor, and click again to create an axis-aligned box first. To rotate it, select the shape in Editing Mode and press `Z`, `X`, `C`, or `V`.
196196
- **Polygon** (`P`): Click along the object's boundary to place vertices. Click the starting point or double-click the last point to close the polygon. Requires at least 3 points. A brush mode (`Ctrl+N`) is also available: once activated, click to place the first point, then move the mouse to automatically trace polygon vertices along the cursor path. Move near the starting point to auto-close. The point distance can be adjusted via `Settings > Canvas > brush.point_distance`.
197197
- **Quadrilateral** (`T`): Click to place the first corner, then click the remaining three corners in order to complete the quadrilateral.
198198
- **Point**: Click to place a point.

docs/zh_cn/user_guide.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ X-AnyLabeling 默认开启自动保存功能,用户在初次启动界面时,
200200
当前,X-AnyLabeling 支持创建以下对象:
201201

202202
- **rectangle**(R):通过左键单击开始绘制,移动光标,左键再次单击结束矩形框绘制;
203-
- **rotation**(O):通过左键单击开始绘制,移动光标,左键再次单击结束旋转框绘制
203+
- **rotation**(O):通过左键单击开始绘制,移动光标,左键再次单击先生成一个水平/竖直方向的旋转框;如需调整角度,可在编辑模式下选中该对象后按 `Z``X``C``V` 旋转
204204
- **polygon**(P):通过左键单击开始绘制,沿着物体边缘点击添加分割点,光标移动到起始顶点处单击即可结束绘制。当前最少需绘制 3 个顶点。另外支持画笔模式(Ctrl+N),激活后单击放置起始点,移动鼠标即可自动沿轨迹添加多边形顶点,光标移至起始点附近自动闭合。画笔点间距可通过 `Settings > Canvas > brush.point_distance` 调整。
205205
- **quadrilateral**(T):通过左键单击开始绘制,依次点击四个顶点,最后一次单击即可结束四边形绘制;
206206
- **point**:通过左键单击即可直接创建关键点;

0 commit comments

Comments
 (0)