# --------------------------------------------------------------------------- # Sky-Plot Widget # --------------------------------------------------------------------------- import math from PyQt5.QtCore import Qt from PyQt5.QtGui import QPainter, QRadialGradient, QColor, QBrush, QPen, QFont from PyQt5.QtWidgets import QWidget from defines import GNSS_NAMES, GNSS_COLORS class SkyPlotWidget(QWidget): def __init__(self, parent=None): super().__init__(parent) self._satellites = [] self.setMinimumSize(400, 400) self.setStyleSheet("background-color: #1a1a2e;") def update_satellites(self, sats: list): self._satellites = sats self.update() def paintEvent(self, event): painter = QPainter(self) painter.setRenderHint(QPainter.Antialiasing) w, h = self.width(), self.height() cx, cy = w / 2, h / 2 radius = min(w, h) / 2 - 30 self._draw_background(painter, cx, cy, radius) self._draw_grid(painter, cx, cy, radius) self._draw_satellites(painter, cx, cy, radius) self._draw_legend(painter) def _draw_background(self, painter, cx, cy, radius): grad = QRadialGradient(cx, cy, radius) grad.setColorAt(0.0, QColor("#0d1b2a")) grad.setColorAt(1.0, QColor("#1a1a2e")) painter.setBrush(QBrush(grad)) painter.setPen(Qt.NoPen) painter.drawEllipse( int(cx - radius), int(cy - radius), int(radius * 2), int(radius * 2), ) def _draw_grid(self, painter, cx, cy, radius): pen = QPen(QColor("#2a4a6a"), 1, Qt.DashLine) painter.setPen(pen) painter.setFont(QFont("Monospace", 8)) for elev in (0, 30, 60): r = radius * (1 - elev / 90) painter.drawEllipse(int(cx - r), int(cy - r), int(r * 2), int(r * 2)) painter.setPen(QColor("#4a7a9b")) painter.drawText(int(cx + 4), int(cy - r), f"{elev}°") painter.setPen(pen) for azim in range(0, 360, 45): rad = math.radians(azim) painter.drawLine( int(cx + math.sin(rad) * radius * 0.05), int(cy - math.cos(rad) * radius * 0.05), int(cx + math.sin(rad) * radius), int(cy - math.cos(rad) * radius), ) painter.setPen(QColor("#7ab7d4")) painter.setFont(QFont("Monospace", 10, QFont.Bold)) for label, azim in (("N", 0), ("O", 90), ("S", 180), ("W", 270)): rad = math.radians(azim) painter.drawText( int(cx + math.sin(rad) * (radius + 15) - 6), int(cy - math.cos(rad) * (radius + 15) + 5), label, ) @staticmethod def _az_el_to_xy(azim, elev, cx, cy, radius): r = radius * (1 - elev / 90) rad = math.radians(azim) return cx + math.sin(rad) * r, cy - math.cos(rad) * r def _draw_satellites(self, painter, cx, cy, radius): for sat in self._satellites: if sat["elev"] < 0: continue color = GNSS_COLORS.get(sat["gnssId"], QColor("#ffffff")) x, y = self._az_el_to_xy(sat["azim"], sat["elev"], cx, cy, radius) cno = max(0, min(50, sat["cno"])) dot_r = 4 + int(cno / 50 * 8) glow = QColor(color) glow.setAlpha(60) painter.setBrush(QBrush(glow)) painter.setPen(Qt.NoPen) painter.drawEllipse( int(x - dot_r * 1.8), int(y - dot_r * 1.8), int(dot_r * 3.6), int(dot_r * 3.6), ) if sat["used"]: painter.setBrush(QBrush(color)) painter.setPen(QPen(QColor("#ffffff"), 1)) else: faded = QColor(color) faded.setAlpha(120) painter.setBrush(QBrush(faded)) painter.setPen(QPen(color, 1, Qt.DashLine)) painter.drawEllipse( int(x - dot_r), int(y - dot_r), dot_r * 2, dot_r * 2 ) painter.setPen(QColor("#ffffff")) painter.setFont(QFont("Monospace", 7)) painter.drawText(int(x + dot_r + 2), int(y + 4), str(sat["svId"])) def _draw_legend(self, painter): painter.setFont(QFont("Monospace", 8)) x, y = 10, 20 for gnss_id, name in GNSS_NAMES.items(): color = GNSS_COLORS[gnss_id] painter.setBrush(QBrush(color)) painter.setPen(Qt.NoPen) painter.drawEllipse(x, y - 8, 10, 10) painter.setPen(QColor("#cccccc")) painter.drawText(x + 14, y, name) y += 16