QChart, как получить очки, которые отображаются при увеличении - PullRequest
0 голосов
/ 12 октября 2018

QChart содержит несколько рядов.

Возможно ли получить список точек, которые в данный момент видны на графике, когда график увеличен?

Означает получение списка / вектораточки фактически отображаемых точек.


Переваривается и упрощается от Кубы ответ:

QList<QVector<QPointF>> XXX::getDisplayedPoints(QChart *chart)
{
   QList<QVector<QPointF>> result;

   foreach (QAbstractSeries * series, chart->series())
   {
       QVector<QPointF> vector;

       auto inScene = chart->plotArea();
       auto inChart = chart->mapFromScene(inScene);
       auto inChartRect = inChart.boundingRect();
       auto inItem1 = chart->mapToValue(inChartRect.topLeft(), series);
       auto inItem2 = chart->mapToValue(inChartRect.bottomRight(), series);
       QRectF rect = QRectF(inItem1, inItem2).normalized();

       const QVector<QPointF> points = static_cast<QLineSeries*>(series)->pointsVector();
       std::copy_if(points.begin(), points.end(), std::back_inserter(vector),
                    [rect](QPointF const &p) { return rect.contains(p); });

       result.append(vector);
   }

   return result;
}

Может вызываться из сигнала

connect(static_cast<QValueAxis *>(m_chart->axisX()), &QValueAxis::rangeChanged, this, &XXX::on_zoomUpdated);

1 Ответ

0 голосов
/ 12 октября 2018

Вам необходимо сопоставить координаты противоположных углов диаграммы plotArea с мировой системой координат ряда, который вы показываете, а затем выполнить итерацию ряда, чтобы извлечь точки, соответствующие этому прямоугольнику.

// https://github.com/KubaO/stackoverflown/tree/master/questionschart-visible-points-52777058
#include <QtCharts>
#include <algorithm>
#include <cmath>

auto seriesRect(QChart *chart, QAbstractSeries *series = nullptr) {
   auto inScene = chart->plotArea();
   auto inChart = chart->mapFromScene(inScene);
   auto inChartRect = inChart.boundingRect();
   auto inItem1 = chart->mapToValue(inChartRect.topLeft(), series);
   auto inItem2 = chart->mapToValue(inChartRect.bottomRight(), series);
   return QRectF(inItem1, inItem2).normalized();
}

auto pointsInRect(QXYSeries *series, const QRectF &rect) {
   QVector<QPointF> result;
   auto const points = series->pointsVector();
   std::copy_if(points.begin(), points.end(), std::back_inserter(result),
                [rect](auto &p) { return rect.contains(p); });
   return result;
}

Остальная часть примера:

screenshot of the example

auto data() {
   QVector<QPointF> result;
   for (auto x = 0.; x < 10.; x += 0.1) result.append({x, exp(x)});
   return result;
}

int main(int argc, char *argv[]) {
   QApplication a(argc, argv);
   QWidget ui;
   QVBoxLayout layout(&ui);
   QChartView view1, view2;
   QLabel status;
   layout.addWidget(&view1);
   layout.addWidget(&view2);
   layout.addWidget(&status);
   layout.setMargin(4);

   QLineSeries series;
   series.replace(data());
   auto *chart = view1.chart();
   chart->addSeries(&series);
   view1.setRubberBand(QChartView::RectangleRubberBand);

   QLineSeries subSeries;
   subSeries.setPointsVisible(true);
   auto *subChart = view2.chart();
   subChart->addSeries(&subSeries);

   for (auto *chart : {view1.chart(), view2.chart()}) {
      chart->legend()->hide();
      chart->createDefaultAxes();
      chart->layout()->setContentsMargins(0, 0, 0, 0);
   }

   auto update = [&] {
      auto rect = seriesRect(chart, &series);
      auto const points = pointsInRect(&series, rect);

      status.setText(QStringLiteral("Visible Range: (%1,%2)-(%3,%4)")
                         .arg(rect.left())
                         .arg(rect.top())
                         .arg(rect.right())
                         .arg(rect.bottom()));

      subSeries.replace(points);
      subChart->axisX(&subSeries)->setRange(rect.left(), rect.right());
      subChart->axisY(&subSeries)->setRange(rect.top(), rect.bottom());
   };
   QObject::connect(chart, &QChart::plotAreaChanged, update);
   ui.setMinimumSize(400, 400);
   ui.show();
   return a.exec();
}

Само отображение см. В этот ответ .

...