mirror of
https://github.com/sunnypilot/sunnypilot.git
synced 2026-02-18 23:33:58 +08:00
cabana: use a segment tree to solve range queries in O(log n) time complexity (#27498)
old-commit-hash: c2018d6bf2
This commit is contained in:
@@ -562,6 +562,9 @@ void ChartView::updateSeries(const Signal *sig, const std::vector<Event *> *even
|
||||
if (events->size()) {
|
||||
s.last_value_mono_time = events->back()->mono_time;
|
||||
}
|
||||
if (!can->liveStreaming()) {
|
||||
s.segment_tree.build(s.vals);
|
||||
}
|
||||
s.series->replace(series_type == SeriesType::StepLine ? s.step_vals : s.vals);
|
||||
}
|
||||
}
|
||||
@@ -586,9 +589,15 @@ void ChartView::updateAxisY() {
|
||||
|
||||
auto first = std::lower_bound(s.vals.begin(), s.vals.end(), axis_x->min(), [](auto &p, double x) { return p.x() < x; });
|
||||
auto last = std::lower_bound(first, s.vals.end(), axis_x->max(), [](auto &p, double x) { return p.x() < x; });
|
||||
for (auto it = first; it != last; ++it) {
|
||||
if (it->y() < min) min = it->y();
|
||||
if (it->y() > max) max = it->y();
|
||||
if (can->liveStreaming()) {
|
||||
for (auto it = first; it != last; ++it) {
|
||||
if (it->y() < min) min = it->y();
|
||||
if (it->y() > max) max = it->y();
|
||||
}
|
||||
} else {
|
||||
auto [min_y, max_y] = s.segment_tree.minmax(std::distance(s.vals.begin(), first), std::distance(s.vals.begin(), last));
|
||||
min = std::min(min, min_y);
|
||||
max = std::max(max, max_y);
|
||||
}
|
||||
}
|
||||
if (min == std::numeric_limits<double>::max()) min = 0;
|
||||
@@ -781,7 +790,7 @@ void ChartView::drawForeground(QPainter *painter, const QRectF &rect) {
|
||||
painter->setPen(Qt::NoPen);
|
||||
qreal track_line_x = -1;
|
||||
for (auto &s : sigs) {
|
||||
if (!s.track_pt.isNull() && s.series->isVisible()) {
|
||||
if (!s.track_pt.isNull() && s.series->isVisible()) {
|
||||
painter->setBrush(s.series->color().darker(125));
|
||||
painter->drawEllipse(s.track_pt, 5.5, 5.5);
|
||||
track_line_x = std::max(track_line_x, s.track_pt.x());
|
||||
|
||||
@@ -46,6 +46,7 @@ public:
|
||||
QVector<QPointF> step_vals;
|
||||
uint64_t last_value_mono_time = 0;
|
||||
QPointF track_pt{};
|
||||
SegmentTree segment_tree;
|
||||
};
|
||||
|
||||
signals:
|
||||
|
||||
@@ -67,6 +67,40 @@ void ChangeTracker::clear() {
|
||||
colors.clear();
|
||||
}
|
||||
|
||||
|
||||
// SegmentTree
|
||||
|
||||
void SegmentTree::build(const QVector<QPointF> &arr) {
|
||||
size = arr.size();
|
||||
tree.resize(4 * size); // size of the tree is 4 times the size of the array
|
||||
if (size > 0) {
|
||||
build_tree(arr, 1, 0, size - 1);
|
||||
}
|
||||
}
|
||||
|
||||
void SegmentTree::build_tree(const QVector<QPointF> &arr, int n, int left, int right) {
|
||||
if (left == right) {
|
||||
const double y = arr[left].y();
|
||||
tree[n] = {y, y};
|
||||
} else {
|
||||
const int mid = (left + right) >> 1;
|
||||
build_tree(arr, 2 * n, left, mid);
|
||||
build_tree(arr, 2 * n + 1, mid + 1, right);
|
||||
tree[n] = {std::min(tree[2 * n].first, tree[2 * n + 1].first), std::max(tree[2 * n].second, tree[2 * n + 1].second)};
|
||||
}
|
||||
}
|
||||
|
||||
std::pair<double, double> SegmentTree::get_minmax(int n, int left, int right, int range_left, int range_right) const {
|
||||
if (range_left > right || range_right < left)
|
||||
return {std::numeric_limits<double>::max(), std::numeric_limits<double>::lowest()};
|
||||
if (range_left <= left && range_right >= right)
|
||||
return tree[n];
|
||||
int mid = (left + right) >> 1;
|
||||
auto l = get_minmax(2 * n, left, mid, range_left, range_right);
|
||||
auto r = get_minmax(2 * n + 1, mid + 1, right, range_left, range_right);
|
||||
return {std::min(l.first, r.first), std::max(l.second, r.second)};
|
||||
}
|
||||
|
||||
// MessageBytesDelegate
|
||||
|
||||
MessageBytesDelegate::MessageBytesDelegate(QObject *parent) : QStyledItemDelegate(parent) {
|
||||
|
||||
@@ -35,6 +35,19 @@ enum {
|
||||
BytesRole = Qt::UserRole + 2
|
||||
};
|
||||
|
||||
class SegmentTree {
|
||||
public:
|
||||
SegmentTree() = default;
|
||||
void build(const QVector<QPointF> &arr);
|
||||
inline std::pair<double, double> minmax(int left, int right) const { return get_minmax(1, 0, size - 1, left, right); }
|
||||
|
||||
private:
|
||||
std::pair<double, double> get_minmax(int n, int left, int right, int range_left, int range_right) const;
|
||||
void build_tree(const QVector<QPointF> &arr, int n, int left, int right);
|
||||
std::vector<std::pair<double ,double>> tree;
|
||||
int size = 0;
|
||||
};
|
||||
|
||||
class MessageBytesDelegate : public QStyledItemDelegate {
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
Reference in New Issue
Block a user