Skip to content

Commit c95fabb

Browse files
committed
add only scaling option to extrinsic
1 parent 4086361 commit c95fabb

8 files changed

Lines changed: 419 additions & 75 deletions

File tree

motion_analysis_2d/custom_components/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from .file_list import FileListWidget
66
from .gui_save_base import BaseGuiSave
77
from .help_widget import HelpView
8+
from .length_item import LengthItem
89
from .my_colors import tab10_rgb, tab10_qcolor, tab10_gbr, tab10_rgb_cycle
910
from .path_edit import PathEdit
1011
from .perspective_item import PerspectiveItem
Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
import pyqtgraph as pg
2+
from qtpy import QtCore, QtGui
3+
4+
5+
class LengthItem(pg.GraphicsObject):
6+
sigLineCornerMoved = QtCore.Signal(int, tuple)
7+
sigMoved = QtCore.Signal(object)
8+
9+
def __init__(
10+
self,
11+
line_corners=((0, 0), (0, 1)),
12+
line_pen=None,
13+
line_hover_pen=None,
14+
handle_size=10,
15+
handle_pen=None,
16+
handle_hover_pen=None,
17+
):
18+
pg.GraphicsObject.__init__(self)
19+
20+
self.line_corners = list(line_corners)
21+
self.handle_size = handle_size
22+
23+
self.handle_hover = [False] * 2
24+
self.handle_dragging = [False] * 2
25+
self.line_hover = False
26+
self.line_dragging = None
27+
28+
self.picture = QtGui.QPicture()
29+
30+
if line_pen is None:
31+
line_pen = pg.mkPen("w", width=2)
32+
self.line_pen = line_pen
33+
34+
if line_hover_pen is None:
35+
line_hover_pen = pg.mkPen("b", width=3)
36+
self.line_hover_pen = line_hover_pen
37+
38+
if handle_pen is None:
39+
handle_pen = pg.mkPen((150, 255, 255), width=1)
40+
self.handle_pen = handle_pen
41+
42+
if handle_hover_pen is None:
43+
handle_hover_pen = pg.mkPen((150, 255, 255), width=3)
44+
self.handle_hover_pen = handle_hover_pen
45+
46+
def generatePicture(self):
47+
if not self.getViewBox():
48+
return
49+
50+
p = QtGui.QPainter(self.picture)
51+
(w, _), (_, h) = self.pixelVectors()
52+
local_handle_size = self.handle_size * w / 2
53+
54+
# line
55+
if self.line_hover:
56+
p.setPen(self.line_hover_pen)
57+
else:
58+
p.setPen(self.line_pen)
59+
p.drawLine(*[QtCore.QPointF(*a) for a in self.line_corners])
60+
61+
# handles for line ends
62+
for point, hover in zip(self.line_corners, self.handle_hover):
63+
if hover:
64+
p.setPen(self.handle_hover_pen)
65+
else:
66+
p.setPen(self.handle_pen)
67+
p.drawEllipse(
68+
QtCore.QRectF(
69+
point[0] - local_handle_size,
70+
point[1] - local_handle_size,
71+
local_handle_size * 2,
72+
local_handle_size * 2,
73+
)
74+
)
75+
p.end()
76+
77+
def paint(self, p, *args):
78+
p.setRenderHint(QtGui.QPainter.RenderHint.Antialiasing)
79+
self.generatePicture()
80+
p.drawPicture(0, 0, self.picture)
81+
82+
def pos_at_handle(self, pos, size):
83+
handles = [False] * 2
84+
for i, point in enumerate(self.line_corners):
85+
d = (pos - QtCore.QPointF(*point)).manhattanLength()
86+
if d <= size * 2:
87+
handles[i] = True
88+
break
89+
return handles
90+
91+
def hoverEvent(self, ev):
92+
self.line_hover = False
93+
94+
if not ev.isExit():
95+
if any(self.handle_dragging) or self.line_dragging is not None:
96+
ev.acceptDrags(QtCore.Qt.LeftButton)
97+
else:
98+
(w, _), (_, h) = self.pixelVectors()
99+
local_handle_size = self.handle_size * w / 2
100+
self.handle_hover = self.pos_at_handle(ev.lastPos(), local_handle_size)
101+
if any(self.handle_hover):
102+
self.update()
103+
return
104+
105+
self.line_hover = True
106+
self.update()
107+
return
108+
else:
109+
self.update()
110+
111+
def mouseDragEvent(self, ev):
112+
if ev.button() != QtCore.Qt.MouseButton.LeftButton:
113+
return
114+
115+
ev.accept()
116+
if ev.isStart() and ev.button() == QtCore.Qt.MouseButton.LeftButton:
117+
if any(self.handle_hover):
118+
self.handle_dragging = self.handle_hover
119+
elif self.line_hover:
120+
pos = ev.pos()
121+
self.line_dragging = [
122+
QtCore.QPointF(*v) - pos for v in self.line_corners
123+
] # offsets
124+
125+
elif ev.isFinish():
126+
self.handle_dragging = [False] * 4
127+
self.line_dragging = None
128+
129+
if any(self.handle_dragging):
130+
i = self.handle_dragging.index(True)
131+
pos = ev.pos().toTuple()
132+
self.line_corners[i] = pos
133+
self.sigLineCornerMoved.emit(i, pos)
134+
self.update()
135+
elif self.line_dragging is not None:
136+
pos = ev.pos()
137+
self.line_corners = [(x + pos).toTuple() for x in self.line_dragging]
138+
self.sigMoved.emit(self.line_corners)
139+
self.update()
140+
141+
def boundingRect(self):
142+
return QtCore.QRectF(self.picture.boundingRect())
143+
144+
def setData(self, line_corners=None, outer_offsets=None):
145+
if line_corners is not None:
146+
self.line_corners = line_corners
147+
148+
def setLineCorner(self, i, pos):
149+
self.line_corners[i] = pos
150+
151+
def setLinePen(self, pen):
152+
self.line_pen = pen
153+
self.update()
154+
155+
def setLineHoverPen(self, pen):
156+
self.line_hover_pen = pen
157+
self.update()
158+
159+
def get_params(self):
160+
return self.line_corners
161+
162+
163+
if __name__ == "__main__":
164+
item = LengthItem(line_corners=((0, 0), (0, 10)))
165+
plt = pg.plot()
166+
plt.addItem(item)
167+
plt.setAspectLocked()
168+
pg.exec()

motion_analysis_2d/dialogs/perspective_dialog.py

Lines changed: 41 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,35 +2,56 @@
22

33

44
class PerspectiveDialog(QtWidgets.QDialog):
5-
completed = QtCore.Signal(float, float)
5+
mode_changed = QtCore.Signal(str)
6+
completed = QtCore.Signal(str, tuple)
67

7-
def __init__(self, title="Adjust perspective"):
8+
def __init__(self, title="Adjust Perspective / Scaling"):
89
super().__init__()
910

1011
self.setWindowFlag(QtCore.Qt.WindowContextHelpButtonHint, False)
1112
self.x_distance = None
1213
self.y_distance = None
14+
self.length = None
1315

14-
self.resize(60, 10)
16+
self.resize(300, 10)
1517
self.setWindowTitle(title)
1618
self.main_layout = QtWidgets.QVBoxLayout(self)
1719

18-
self.form_layout = QtWidgets.QFormLayout()
19-
self.main_layout.addLayout(self.form_layout)
20+
self.mode_combobox = QtWidgets.QComboBox(self)
21+
self.mode_combobox.addItems(["Perspective", "Scaling"])
22+
self.mode_combobox.activated.connect(self.switch_page)
23+
self.main_layout.addWidget(self.mode_combobox)
24+
25+
self.stacked_layout = QtWidgets.QStackedLayout()
26+
self.main_layout.addLayout(self.stacked_layout)
27+
28+
self.perspective_page = QtWidgets.QWidget(self)
29+
self.perspective_form_layout = QtWidgets.QFormLayout(self.perspective_page)
30+
self.stacked_layout.addWidget(self.perspective_page)
2031

2132
self.x_spinbox = QtWidgets.QDoubleSpinBox(self)
2233
self.x_spinbox.setRange(0, 10**5)
2334
self.x_spinbox.setDecimals(3)
2435
self.x_spinbox.setValue(0)
2536
self.x_spinbox.setSpecialValueText("Auto")
26-
self.form_layout.addRow("X: ", self.x_spinbox)
37+
self.perspective_form_layout.addRow("X: ", self.x_spinbox)
2738

2839
self.y_spinbox = QtWidgets.QDoubleSpinBox(self)
2940
self.y_spinbox.setRange(0, 10**5)
3041
self.y_spinbox.setDecimals(3)
3142
self.y_spinbox.setValue(0)
3243
self.y_spinbox.setSpecialValueText("Auto")
33-
self.form_layout.addRow("Y: ", self.y_spinbox)
44+
self.perspective_form_layout.addRow("Y: ", self.y_spinbox)
45+
46+
self.scaling_page = QtWidgets.QWidget(self)
47+
self.scaling_form_layout = QtWidgets.QFormLayout(self.scaling_page)
48+
self.stacked_layout.addWidget(self.scaling_page)
49+
50+
self.length_spinbox = QtWidgets.QDoubleSpinBox(self)
51+
self.length_spinbox.setRange(0, 10**5)
52+
self.length_spinbox.setDecimals(3)
53+
self.length_spinbox.setValue(1)
54+
self.scaling_form_layout.addRow("Length: ", self.length_spinbox)
3455

3556
self.main_layout.addStretch()
3657

@@ -40,10 +61,22 @@ def __init__(self, title="Adjust perspective"):
4061

4162
self.main_layout.addStretch()
4263

64+
def switch_page(self):
65+
self.stacked_layout.setCurrentIndex(self.mode_combobox.currentIndex())
66+
self.mode_changed.emit(self.mode())
67+
68+
def mode(self):
69+
return self.mode_combobox.currentText()
70+
4371
def ok_clicked(self):
4472
self.x_distance = self.x_spinbox.value()
4573
self.y_distance = self.y_spinbox.value()
46-
self.completed.emit(self.x_distance, self.y_distance)
74+
self.length = self.length_spinbox.value()
75+
mode = self.mode_combobox.currentText()
76+
if mode == "Perspective":
77+
self.completed.emit(mode, (self.x_distance, self.y_distance))
78+
elif mode == "Scaling":
79+
self.completed.emit(mode, (self.length,))
4780

4881
self.accept()
4982
self.close()

0 commit comments

Comments
 (0)