#include "tools/cabana/chart/sparkline.h" #include #include #include void Sparkline::update(const MessageId &msg_id, const cabana::Signal *sig, double last_msg_ts, int range, QSize size) { points.clear(); double value = 0; auto [first, last] = can->eventsInRange(msg_id, std::make_pair(last_msg_ts -range, last_msg_ts)); for (auto it = first; it != last; ++it) { if (sig->getValue((*it)->dat, (*it)->size, &value)) { points.emplace_back(((*it)->mono_time - (*first)->mono_time) / 1e9, value); } } if (points.empty() || size.isEmpty()) { pixmap = QPixmap(); return; } const auto [min, max] = std::minmax_element(points.begin(), points.end(), [](auto &l, auto &r) { return l.y() < r.y(); }); min_val = min->y() == max->y() ? min->y() - 1 : min->y(); max_val = min->y() == max->y() ? max->y() + 1 : max->y(); freq_ = points.size() / std::max(points.back().x() - points.front().x(), 1.0); render(sig->color, range, size); } void Sparkline::render(const QColor &color, int range, QSize size) { const double xscale = (size.width() - 1) / (double)range; const double yscale = (size.height() - 3) / (max_val - min_val); for (auto &v : points) { v = QPoint(v.x() * xscale, 1 + std::abs(v.y() - max_val) * yscale); } qreal dpr = qApp->devicePixelRatio(); size *= dpr; if (size != pixmap.size()) { pixmap = QPixmap(size); } pixmap.setDevicePixelRatio(dpr); pixmap.fill(Qt::transparent); QPainter painter(&pixmap); painter.setRenderHint(QPainter::Antialiasing, points.size() < 500); painter.setPen(color); painter.drawPolyline(points.data(), points.size()); painter.setPen(QPen(color, 3)); if ((points.back().x() - points.front().x()) / points.size() > 8) { painter.drawPoints(points.data(), points.size()); } else { painter.drawPoint(points.back()); } }