Hi Uwe,

so.. I have implemented it with this way (I use 10 000 000 of points for example, also it works with 50 000 000 points):

Qt Code:
  1. // SourceSamples
  2.  
  3. class SourceSamples : public QwtSeriesData<QPointF>
  4. {
  5. public:
  6. explicit SourceSamples();
  7.  
  8. private: // virtual overrides
  9. size_t size() const final;
  10. QPointF sample(size_t i) const final;
  11. void setRectOfInterest(const QRectF &rect) final;
  12. QRectF boundingRect() const final;
  13.  
  14. private:
  15. static size_t getFactor(size_t pointsCount);
  16.  
  17. void updateCache(const QRectF &rect);
  18.  
  19. private:
  20. // Emulates the data from the external storage (e.g. file or DB).
  21. QVector<QPointF> m_storage;
  22. // Set of samples for current details level.
  23. QVector<QPointF> m_cache;
  24. };
  25.  
  26. // Calculates factor which allow to have always ~500 points to draw.
  27. size_t SourceSamples::getFactor(size_t pointsCount)
  28. {
  29. const auto factor = pointsCount / 500;
  30. return (factor > 0) ? factor : 1;
  31. }
  32.  
  33. // Refills the internal samples cache for the required rect.
  34. void SourceSamples::updateCache(const QRectF &rect)
  35. {
  36. // Binary search indexes of minimum and maximum points for
  37. // the X-axis of passed rect in "external" data storage
  38. // (which is simulates by the m_storage in our cases).
  39. const auto begin = m_storage.cbegin();
  40. const auto end = m_storage.cend();
  41.  
  42. auto compare = [](const QPointF &p1, const QPointF &p2) {
  43. return p1.x() < p2.x(); };
  44.  
  45. // Find iterator of minimal point.
  46. const QPointF p1(rect.x(), 0);
  47. auto lower = std::lower_bound(begin, end, p1, compare);
  48. // Find iterator of maximum point.
  49. const QPointF p2(rect.x() + rect.width(), 0);
  50. auto upper = std::upper_bound(begin, end, p2, compare);
  51.  
  52. // TODO: Should we to do this?
  53. if (lower == end)
  54. lower = begin;
  55. if (upper == end)
  56. upper = end - 1;
  57.  
  58. // Calculate indexed of points in "external" storage.
  59. // (in principle, it can be omitted, as we have iterators).
  60. const auto lowerIndex = std::distance(begin, lower);
  61. const auto upperIndex = std::distance(begin, upper);
  62. auto pointsCount = upperIndex - lowerIndex;
  63.  
  64. // Get required "weeding" factor.
  65. const size_t factor = getFactor(pointsCount);
  66. qDebug() << "New factor" << factor << "for" << pointsCount << "points"
  67. << "from" << lowerIndex << "," << p1.x()
  68. << "to" << upperIndex << "," << p2.x();
  69.  
  70. // Desired number of points, which will be displayed.
  71. pointsCount = qRound(pointsCount / double(factor)) + 1;
  72. qDebug() << "Reduced up to" << pointsCount << "points";
  73.  
  74. // Refill the cache again with every "factor" step.
  75. m_cache.clear();
  76. // Always add the minimum point of range.
  77. m_cache += m_storage.at(lowerIndex);
  78. for (size_t i = 1; i < pointsCount - 1; ++i) {
  79. // Add the middle points.
  80. const size_t n =(i * factor) + lowerIndex;
  81. m_cache += m_storage.at(n);
  82. }
  83. // Always add the maximum point of range.
  84. m_cache += m_storage.at(upperIndex);
  85. }
  86.  
  87. SourceSamples::SourceSamples()
  88. {
  89. // Fill the "external" storage with all available points
  90. // (we just emulate the external storage as file, or DB,
  91. // via the array of data, for simplification of a code.
  92. size_t pointsCount = 10000000;
  93. m_storage.resize(pointsCount);
  94. double x = 0.0;
  95. for (size_t i = 0; i < pointsCount; ++i) {
  96. double y = std::sin(x);
  97. m_storage[i] = { x, y };
  98. x += 0.01;
  99. }
  100.  
  101. // Fill the cache for the initial details level. We starts
  102. // it for "low" resolution (we want to view whole range).
  103. const size_t factor = getFactor(m_storage.size());
  104. pointsCount = qRound(m_storage.size() / double(factor)) + 1;
  105. qDebug() << Q_FUNC_INFO << "Initialize with" << pointsCount << "points";
  106.  
  107. // Fill the cache with every "factor" step.
  108. // Always add the minimum point of range.
  109. m_cache += m_storage.first();
  110. for (size_t i = 1; i < pointsCount - 1; ++i) {
  111. const size_t n = i * factor;
  112. // Add the middle points.
  113. m_cache += m_storage.at(n);
  114. }
  115. // Always add the maximum point of range.
  116. m_cache += m_storage.last();
  117. }
  118.  
  119. size_t SourceSamples::size() const
  120. {
  121. return m_cache.size();
  122. }
  123.  
  124. QPointF SourceSamples::sample(size_t i) const
  125. {
  126. return m_cache.at(i);
  127. }
  128.  
  129. void SourceSamples::setRectOfInterest(const QRectF &rect)
  130. {
  131. updateCache(rect);
  132.  
  133. // TODO: Should we to do it?
  134. d_boundingRect = rect;
  135. }
  136.  
  137. QRectF SourceSamples::boundingRect() const
  138. {
  139. if (d_boundingRect.width() < 0.0)
  140. d_boundingRect = qwtBoundingRect(*this);
  141. return d_boundingRect;
  142. }
  143.  
  144. // RandomPlot
  145.  
  146. RandomPlot::RandomPlot(QWidget *parent)
  147. : QwtPlot(parent)
  148. {
  149. setAutoReplot(false);
  150.  
  151. auto grid = new QwtPlotGrid;
  152. grid->enableXMin(true);
  153. grid->setMajorPen(QPen(Qt::black, 0, Qt::DotLine));
  154. grid->setMinorPen(QPen(Qt::gray, 0, Qt::DotLine));
  155. grid->attach(this);
  156.  
  157. auto zoomer = new QwtPlotZoomer(canvas());
  158. // We want to have a zoom with the X-axis only.
  159. zoomer->setAxes(QwtPlot::xBottom, QwtPlot::yRight);
  160.  
  161. auto curve = new QwtPlotCurve;
  162. curve->setItemInterest(QwtPlotCurve::ScaleInterest, true);
  163.  
  164. auto series = new SourceSamples;
  165. curve->setData(series);
  166. curve->attach(this);
  167. }
To copy to clipboard, switch view to plain text mode 

seems, it works, but I'm not sure that it is right idea...

@Uwe,

Could you please comment of this idea? Maybe it can be optimized or changed at all?

Also I have additional questions:

1. Should I update the d_boundingRect with "interest rect" in this? Or, I need do not touch d_boundingRect at all?

Qt Code:
  1. void SourceSamples::setRectOfInterest(const QRectF &rect)
  2. {
  3. updateCache(rect);
  4.  
  5. // TODO: Should we to do it?
  6. d_boundingRect = rect;
  7. }
To copy to clipboard, switch view to plain text mode 

2. Why, when I do "comments out" of this code:

Qt Code:
  1. ...
  2. //curve->setItemInterest(QwtPlotCurve::ScaleInterest, true);
  3. ...
To copy to clipboard, switch view to plain text mode 

then the method SourceSamples::setRectOfInterest() were called? The QwtPlotCurve::ScaleInterest has not effect?