From 52a8a95a8553f5b2a1224db474e6cf1d649533c8 Mon Sep 17 00:00:00 2001 From: Paweł Redman Date: Sun, 28 Apr 2019 17:29:18 +0200 Subject: Initial commit --- src/ui_widgets.py | 226 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 226 insertions(+) create mode 100644 src/ui_widgets.py (limited to 'src/ui_widgets.py') diff --git a/src/ui_widgets.py b/src/ui_widgets.py new file mode 100644 index 0000000..48282c4 --- /dev/null +++ b/src/ui_widgets.py @@ -0,0 +1,226 @@ +import numpy as np +from PyQt5.QtWidgets import * +from PyQt5.QtGui import * +from PyQt5.QtCore import * + +from ui import GUI, Pens # the fuck + +class ExpandingSpacer(QSpacerItem): + def __init__(self): + super().__init__(0, 0, QSizePolicy.Minimum, \ + QSizePolicy.Expanding) + +class MeinLabel(QLabel): + def __init__(self, *args): + QLabel.__init__(self, *args) + self.setFont(GUI.monospace) + +class MeinGroßLabel(QLabel): + def __init__(self, *args): + QLabel.__init__(self, *args) + self.setFont(GUI.bigfont) + self.setAlignment(Qt.AlignHCenter) + +class EllipseWidget(QWidget): + def __init__(self, pol): + QWidget.__init__(self) + self.pol = pol + self.state = None + self.ellipse = None + self.is_used = True + + def minimumSizeHint(self): + return QSize(150, 150) + + def paintEvent(self, event): + P = QPainter(self) + + w, h = self.frameSize().width(), self.frameSize().height() + cx, cy = w / 2, h / 2 + r = min(w, h) / 2 + + # background + if self.is_used: + background = Qt.white + else: + background = QColor(0, 0, 0, 100) + P.fillRect(QRect(0, 0, w, h), background) + + # coordinate axes + P.setPen(Pens.axes) + P.drawLine(cx - 20 * r, cy, cx + 20 * r, cy) + P.drawLine(cx, cy - 20 * r, cx, cy + 20 * r) + + # polarizer axes + P.translate(cx, cy) + P.rotate(- (self.pol.angle + self.pol.delta) * 180 / np.pi) + if self.pol.type == "linear": + P.setPen(Pens.axis_linear) + P.drawLine(-20 * r, 0, 20 * r, 0) + else: + P.setPen(Pens.axis_fast) + P.drawLine(-20 * r, 0, 20 * r, 0) + P.drawText(0.92 * r, 0, "F") + P.setPen(Pens.axis_slow) + P.drawLine(0, -20 * r, 0, 20 * r) + P.drawText(0, -0.92 * r, "S") + + if self.state is None: + return + + P.resetTransform() + r *= 0.88 + P.translate(cx, cy) + P.scale(1, -1) + + # radii + P.setPen(Pens.radii) + csa = np.array([np.cos(self.ellipse.alpha), np.sin(self.ellipse.alpha)]) + xa = self.ellipse.a * r * csa + P.drawLine(-xa[0], -xa[1], xa[0], xa[1]) + csb = np.array([np.cos(self.ellipse.alpha + np.pi / 2), \ + np.sin(self.ellipse.alpha + np.pi / 2)]) + xb = self.ellipse.b * r * csb + P.drawLine(-xb[0], -xb[1], xb[0], xb[1]) + + def arc(x, y, r, t1, t2): + P.drawArc(x - r / 2, y - r / 2, r, r, \ + -180 * 16 / np.pi * t1, \ + -180 * 16 / np.pi * t2) + + # azimuth + P.setPen(Pens.alpha) + P.drawLine(0, 0, xa[0], xa[1]) + arc(0, 0, self.ellipse.a * r, 0, self.ellipse.alpha) + + # ellipticity + P.setPen(Pens.theta) + P.drawLine(-xa[0], -xa[1], xb[0], xb[1]) + arc(-xa[0], -xa[1], r / 2, self.ellipse.alpha, abs(self.ellipse.theta)) + + # the ellipse + P.setPen(Pens.ellipse) + path = QPainterPath() + for i, t in enumerate(np.linspace(0, 2 * np.pi, 100)): + x = r * np.real(np.exp(1j * t) * self.state) + f = path.moveTo if t == 0 else path.lineTo # FML + f(x[0], x[1]) # +Y should be upwards + + if abs(self.ellipse.theta) > 0.05 and i % 25 == 0: + N = r * np.real(np.exp(1j * (t + 0.001)) * self.state) - x + N /= np.linalg.norm(N) + if np.any(np.isnan(N)): + continue + + T = np.dot(np.array([[0, 1], [-1, 0]]), N) + + ax = x - N * 5 + T * 5 + P.drawLine(x[0], x[1], ax[0], ax[1]) + ax = x - N * 5 - T * 5 + P.drawLine(x[0], x[1], ax[0], ax[1]) + path.closeSubpath() + P.drawPath(path) + + if abs(self.ellipse.theta) <= 0.05: + x1 = xa - r / 20 * csb + x2 = xa + r / 20 * csb + P.drawLine(x1[0], x1[1], x2[0], x2[1]) + x1 = -xa - r / 20 * csb + x2 = -xa + r / 20 * csb + P.drawLine(x1[0], x1[1], x2[0], x2[1]) + + + +class AngleSlider(QHBoxLayout): + def __init__(self, label=None): + super().__init__() + self.angle = 0 + + if label: + self.addWidget(QLabel(label)) + + self.slider = QSlider(Qt.Horizontal) + self.slider.setMinimumWidth(100) + self.slider.setMinimum(0) + self.slider.setMaximum(180) + self.slider.setTickPosition(QSlider.TicksBelow) + self.slider.setTickInterval(45) + self.slider.valueChanged.connect(\ + lambda: AngleSlider.change(self, "bar")) + self.addWidget(self.slider) + + self.edit = QLineEdit() + self.edit.setText("0") + self.edit.setMinimumWidth(30) + self.edit.textChanged.connect(\ + lambda: AngleSlider.change(self, "edit")) + self.addWidget(self.edit) + self.addWidget(QLabel("°")) + + def setValue(self, angle): + self.angle = angle + self.slider.blockSignals(True) + self.slider.setValue(angle) + self.slider.blockSignals(False) + self.edit.blockSignals(True) + self.edit.setText("%g" % angle) + self.edit.blockSignals(False) + + @staticmethod + def change(self, source): + if source == "edit": + try: + angle = float(self.edit.text()) + except ValueError: + return + self.slider.blockSignals(True) + self.slider.setValue(angle) + self.slider.blockSignals(False) + elif source == "bar": + angle = self.slider.value() + self.edit.blockSignals(True) + self.edit.setText("%g" % angle) + self.edit.blockSignals(False) + self.angle = angle + self.on_change() + + + +class Widocques(QWidget): + image = None + + def __init__(self): + QWidget.__init__(self) + self.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)) + self.intensity = 1 + + def minimumSizeHint(self): + return QSize(100, 100) + + def paintEvent(self, event): + P = QPainter(self) + + w, h = self.frameSize().width(), self.frameSize().height() + + ar = Widocques.image.width() \ + / Widocques.image.height() + + if w / h > ar: + # pad left/right + w2 = h * ar + pad = (w - w2) / 2 + rect = QRect(pad, 0, w2, h) + else: + # pad top/bottom + h2 = w / ar + pad = (h - h2) / 2 + rect = QRect(0, pad, w, h2) + + w2 = rect.width() + h2 = rect.height() + rect2 = QRect(rect.left() + 0.1 * w2, rect.top() + 0.1 * h2, \ + w2 * 0.8, h2 * 0.8) + + P.fillRect(QRect(0, 0, w, h), Qt.black) + P.drawImage(rect2, Widocques.image) + P.fillRect(rect2, QColor(0, 0, 0, 255 * (1 - self.intensity))) -- cgit