2
KDChart - a multi-platform charting engine
5
/****************************************************************************
6
** Copyright (C) 2005-2007 Klarälvdalens Datakonsult AB. All rights reserved.
8
** This file is part of the KD Chart library.
10
** This file may be used under the terms of the GNU General Public
11
** License versions 2.0 or 3.0 as published by the Free Software
12
** Foundation and appearing in the files LICENSE.GPL2 and LICENSE.GPL3
13
** included in the packaging of this file. Alternatively you may (at
14
** your option) use any later version of the GNU General Public
15
** License if such license has been publicly approved by
16
** Klarälvdalens Datakonsult AB (or its successors, if any).
18
** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
19
** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
20
** A PARTICULAR PURPOSE. Klarälvdalens Datakonsult AB reserves all rights
21
** not expressly granted herein.
23
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
24
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
26
**********************************************************************/
28
#include "KDChartCartesianDiagramDataCompressor_p.h"
31
#include <QAbstractItemModel>
33
#include "KDChartAbstractCartesianDiagram.h"
35
#include <KDABLibFakes>
37
using namespace KDChart;
40
CartesianDiagramDataCompressor::CartesianDiagramDataCompressor( QObject* parent )
46
, m_datasetDimension( 1 )
48
calculateSampleStepWidth();
51
QModelIndexList CartesianDiagramDataCompressor::indexesAt( const CachePosition& position ) const
53
if ( isValidCachePosition( position ) ) {
54
CachePosition posPrev( position );
55
if( m_datasetDimension == 2 ){
62
const QModelIndexList indPrev = mapToModel( posPrev );
63
const QModelIndexList indCur = mapToModel( position );
65
QModelIndexList indexes;
66
if( m_datasetDimension == 2 )
68
const int iStart = (indPrev.empty() || indPrev==indCur) ? indCur.first().column()
69
: indPrev.first().column() + 1;
70
const int iEnd = indCur.last().column();
71
for( int i=iStart; i<=iEnd; ++i){
72
indexes << m_model->index( position.first, i, m_rootIndex );
77
const int iStart = (indPrev.empty() || indPrev==indCur) ? indCur.first().row()
78
: indPrev.first().row() + 1;
79
const int iEnd = (indCur.isEmpty()) ? iStart : indCur.first().row();
80
//qDebug()<<iStart<<iEnd << iEnd-iStart;
81
for( int i=iStart; i<=iEnd; ++i){
82
indexes << m_model->index( i, position.second, m_rootIndex );
87
return QModelIndexList();
92
CartesianDiagramDataCompressor::DataValueAttributesList CartesianDiagramDataCompressor::aggregatedAttrs(
93
AbstractDiagram * diagram,
94
const QModelIndex & index,
95
const CachePosition& position ) const
97
// return cached attrs, if any
98
DataValueAttributesCache::const_iterator i = m_dataValueAttributesCache.constFind(position);
99
if( i != m_dataValueAttributesCache.constEnd() )
101
// retrieve attrs from all cells between the prev. cell and the current one
102
CartesianDiagramDataCompressor::DataValueAttributesList allAttrs;
103
const QModelIndexList indexes( indexesAt( position ) );
104
KDAB_FOREACH( QModelIndex idx, indexes ) {
105
DataValueAttributes attrs( diagram->dataValueAttributes( idx ) );
106
if( attrs.isVisible() ){
107
// make sure no duplicate attrs are stored
108
bool isDuplicate = false;
109
CartesianDiagramDataCompressor::DataValueAttributesList::const_iterator i = allAttrs.constBegin();
110
while (i != allAttrs.constEnd()) {
111
if( i.value() == attrs ){
118
//qDebug()<<idx.row();
119
allAttrs[idx] = attrs;
123
// if none of the attrs had the visible flag set
124
// we just take the one set for the index to not return an empty list
125
if( allAttrs.empty() ){
126
allAttrs[index] = diagram->dataValueAttributes( index );
129
m_dataValueAttributesCache[position] = allAttrs;
134
void CartesianDiagramDataCompressor::slotRowsAboutToBeInserted( const QModelIndex& parent, int start, int end )
136
if ( parent != m_rootIndex )
138
Q_ASSERT( start <= end );
140
CachePosition startPos = mapToCache( start, 0 );
141
CachePosition endPos = mapToCache( end, 0 );
143
static const CachePosition NullPosition( -1, -1 );
144
if( startPos == NullPosition )
147
startPos = mapToCache( start, 0 );
148
endPos = mapToCache( end, 0 );
149
// The start position still isn't valid,
150
// means that no resolution was set yet or we're about to add the first rows
151
if( startPos == NullPosition ) {
156
start = startPos.first;
159
for( int i = 0; i < m_data.size(); ++i )
161
Q_ASSERT( start >= 0 && start <= m_data[ i ].size() );
162
m_data[ i ].insert( start, end - start + 1, DataPoint() );
166
void CartesianDiagramDataCompressor::slotRowsInserted( const QModelIndex& parent, int start, int end )
168
if ( parent != m_rootIndex )
170
Q_ASSERT( start <= end );
172
CachePosition startPos = mapToCache( start, 0 );
173
CachePosition endPos = mapToCache( end, 0 );
175
static const CachePosition NullPosition( -1, -1 );
176
if( startPos == NullPosition )
178
// Rebuild the cache at this point if we have added the first rows
180
startPos = mapToCache( start, 0 );
181
endPos = mapToCache( end, 0 );
182
// The start position still isn't valid,
183
// means that no resolution was set yet
184
if( startPos == NullPosition ) {
189
start = startPos.first;
192
for( int i = 0; i < m_data.size(); ++i )
194
for( int j = start; j < m_data[i].size(); ++j ) {
195
retrieveModelData( CachePosition( j, i ) );
200
void CartesianDiagramDataCompressor::slotColumnsAboutToBeInserted( const QModelIndex& parent, int start, int end )
202
if ( parent != m_rootIndex )
204
Q_ASSERT( start <= end );
206
CachePosition startPos = mapToCache( 0, start );
207
CachePosition endPos = mapToCache( 0, end );
209
static const CachePosition NullPosition( -1, -1 );
210
if( startPos == NullPosition )
213
startPos = mapToCache( 0, start );
214
endPos = mapToCache( 0, end );
215
// The start position still isn't valid,
216
// means that no resolution was set yet or we're about to add the first columns
217
if( startPos == NullPosition ) {
222
start = startPos.second;
225
const int rowCount = qMin( m_model ? m_model->rowCount( m_rootIndex ) : 0, m_xResolution );
226
Q_ASSERT( start >= 0 && start <= m_data.size() );
227
m_data.insert( start, end - start + 1, QVector< DataPoint >( rowCount ) );
230
void CartesianDiagramDataCompressor::slotColumnsInserted( const QModelIndex& parent, int start, int end )
232
if ( parent != m_rootIndex )
234
Q_ASSERT( start <= end );
236
CachePosition startPos = mapToCache( 0, start );
237
CachePosition endPos = mapToCache( 0, end );
239
static const CachePosition NullPosition( -1, -1 );
240
if( startPos == NullPosition )
242
// Rebuild the cache at this point if we have added the first columns
244
startPos = mapToCache( 0, start );
245
endPos = mapToCache( 0, end );
246
// The start position still isn't valid,
247
// means that no resolution was set yet
248
if( startPos == NullPosition ) {
253
start = startPos.second;
256
for( int i = start; i < m_data.size(); ++i )
258
for(int j = 0; j < m_data[i].size(); ++j ) {
259
retrieveModelData( CachePosition( j, i ) );
264
void CartesianDiagramDataCompressor::slotRowsAboutToBeRemoved( const QModelIndex& parent, int start, int end )
266
if ( parent != m_rootIndex )
268
Q_ASSERT( start <= end );
270
CachePosition startPos = mapToCache( start, 0 );
271
CachePosition endPos = mapToCache( end, 0 );
273
static const CachePosition NullPosition( -1, -1 );
274
if( startPos == NullPosition )
277
startPos = mapToCache( start, 0 );
278
endPos = mapToCache( end, 0 );
279
// The start position still isn't valid,
280
// probably means that no resolution was set yet
281
if( startPos == NullPosition ) {
286
start = startPos.first;
289
for( int i = 0; i < m_data.size(); ++i )
291
m_data[ i ].remove( start, end - start + 1 );
295
void CartesianDiagramDataCompressor::slotRowsRemoved( const QModelIndex& parent, int start, int end )
297
if ( parent != m_rootIndex )
299
Q_ASSERT( start <= end );
301
CachePosition startPos = mapToCache( start, 0 );
302
CachePosition endPos = mapToCache( end, 0 );
304
start = startPos.first;
307
static const CachePosition NullPosition( -1, -1 );
308
if( startPos == NullPosition )
310
// Since we should already have rebuilt the cache, it won't help to rebuild it again.
311
// Do not Q_ASSERT() though, since the resolution might simply not be set or we might now have 0 rows
315
for( int i = 0; i < m_data.size(); ++i ) {
316
for(int j = start; j < m_data[i].size(); ++j ) {
317
retrieveModelData( CachePosition( j, i ) );
322
void CartesianDiagramDataCompressor::slotColumnsAboutToBeRemoved( const QModelIndex& parent, int start, int end )
324
if ( parent != m_rootIndex )
326
Q_ASSERT( start <= end );
328
CachePosition startPos = mapToCache( 0, start );
329
CachePosition endPos = mapToCache( 0, end );
331
static const CachePosition NullPosition( -1, -1 );
332
if( startPos == NullPosition )
335
startPos = mapToCache( 0, start );
336
endPos = mapToCache( 0, end );
337
// The start position still isn't valid,
338
// probably means that no resolution was set yet
339
if( startPos == NullPosition ) {
344
start = startPos.second;
347
m_data.remove( start, end - start + 1 );
350
void CartesianDiagramDataCompressor::slotColumnsRemoved( const QModelIndex& parent, int start, int end )
352
if ( parent != m_rootIndex )
354
Q_ASSERT( start <= end );
356
const CachePosition startPos = mapToCache( 0, start );
357
const CachePosition endPos = mapToCache( 0, end );
359
start = startPos.second;
362
static const CachePosition NullPosition( -1, -1 );
363
if( startPos == NullPosition )
365
// Since we should already have rebuilt the cache, it won't help to rebuild it again.
366
// Do not Q_ASSERT() though, since the resolution might simply not be set or we might now have 0 columns
370
for( int i = start; i < m_data.size(); ++i ) {
371
for( int j = 0; j < m_data[i].size(); ++j ) {
372
retrieveModelData( CachePosition( j, i ) );
377
void CartesianDiagramDataCompressor::slotModelHeaderDataChanged( Qt::Orientation orientation, int first, int last )
379
if( orientation != Qt::Vertical )
382
const QModelIndex firstRow = m_model->index( 0, first, m_rootIndex );
383
const QModelIndex lastRow = m_model->index( m_model->rowCount( m_rootIndex ) - 1, last, m_rootIndex );
385
slotModelDataChanged( firstRow, lastRow );
388
void CartesianDiagramDataCompressor::slotModelDataChanged(
389
const QModelIndex& topLeftIndex,
390
const QModelIndex& bottomRightIndex )
392
if ( topLeftIndex.parent() != m_rootIndex )
394
Q_ASSERT( topLeftIndex.parent() == bottomRightIndex.parent() );
395
Q_ASSERT( topLeftIndex.row() <= bottomRightIndex.row() );
396
Q_ASSERT( topLeftIndex.column() <= bottomRightIndex.column() );
397
CachePosition topleft = mapToCache( topLeftIndex );
398
CachePosition bottomright = mapToCache( bottomRightIndex );
399
for ( int row = topleft.first; row <= bottomright.first; ++row )
400
for ( int column = topleft.second; column <= bottomright.second; ++column )
401
invalidate( CachePosition( row, column ) );
404
void CartesianDiagramDataCompressor::slotModelLayoutChanged()
407
calculateSampleStepWidth();
410
void CartesianDiagramDataCompressor::slotDiagramLayoutChanged( AbstractDiagram* diagramBase )
412
AbstractCartesianDiagram* diagram = qobject_cast< AbstractCartesianDiagram* >( diagramBase );
414
if ( diagram->datasetDimension() != m_datasetDimension ) {
415
setDatasetDimension( diagram->datasetDimension() );
419
int CartesianDiagramDataCompressor::modelDataColumns() const
421
Q_ASSERT( m_datasetDimension != 0 );
422
// only operational if there is a model and a resolution
424
const int columns = m_model->columnCount( m_rootIndex ) / m_datasetDimension;
426
if( columns != m_data.size() )
431
Q_ASSERT( columns == m_data.size() );
438
int CartesianDiagramDataCompressor::modelDataRows() const
440
// only operational if there is a model, columns, and a resolution
441
if ( m_model && m_model->columnCount( m_rootIndex ) > 0 && m_xResolution > 0 ) {
442
return m_data.isEmpty() ? 0 : m_data.first().size();
448
void CartesianDiagramDataCompressor::setModel( QAbstractItemModel* model )
450
if ( m_model != 0 && m_model != model ) {
451
disconnect( m_model, SIGNAL( headerDataChanged( Qt::Orientation, int, int ) ),
452
this, SLOT( slotModelHeaderDataChanged( Qt::Orientation, int, int ) ) );
453
disconnect( m_model, SIGNAL( dataChanged( QModelIndex, QModelIndex ) ),
454
this, SLOT( slotModelDataChanged( QModelIndex, QModelIndex ) ) );
455
disconnect( m_model, SIGNAL( layoutChanged() ),
456
this, SLOT( slotModelLayoutChanged() ) );
457
disconnect( m_model, SIGNAL( rowsAboutToBeInserted( QModelIndex, int, int ) ),
458
this, SLOT( slotRowsAboutToBeInserted( QModelIndex, int, int ) ) );
459
disconnect( m_model, SIGNAL( rowsInserted( QModelIndex, int, int ) ),
460
this, SLOT( slotRowsInserted( QModelIndex, int, int ) ) );
461
disconnect( m_model, SIGNAL( rowsAboutToBeRemoved( QModelIndex, int, int ) ),
462
this, SLOT( slotRowsAboutToBeRemoved( QModelIndex, int, int ) ) );
463
disconnect( m_model, SIGNAL( rowsRemoved( QModelIndex, int, int ) ),
464
this, SLOT( slotRowsRemoved( QModelIndex, int, int ) ) );
465
disconnect( m_model, SIGNAL( columnsAboutToBeInserted( QModelIndex, int, int ) ),
466
this, SLOT( slotColumnsAboutToBeInserted( QModelIndex, int, int ) ) );
467
disconnect( m_model, SIGNAL( columnsInserted( QModelIndex, int, int ) ),
468
this, SLOT( slotColumnsInserted( QModelIndex, int, int ) ) );
469
disconnect( m_model, SIGNAL( columnsRemoved( QModelIndex, int, int ) ),
470
this, SLOT( slotColumnsRemoved( QModelIndex, int, int ) ) );
471
disconnect( m_model, SIGNAL( columnsAboutToBeRemoved( QModelIndex, int, int ) ),
472
this, SLOT( slotColumnsAboutToBeRemoved( QModelIndex, int, int ) ) );
473
disconnect( m_model, SIGNAL( modelReset() ),
474
this, SLOT( rebuildCache() ) );
478
m_modelCache.setModel( model );
482
connect( m_model, SIGNAL( headerDataChanged( Qt::Orientation, int, int ) ),
483
SLOT( slotModelHeaderDataChanged( Qt::Orientation, int, int ) ) );
484
connect( m_model, SIGNAL( dataChanged( QModelIndex, QModelIndex ) ),
485
SLOT( slotModelDataChanged( QModelIndex, QModelIndex ) ) );
486
connect( m_model, SIGNAL( layoutChanged() ),
487
SLOT( slotModelLayoutChanged() ) );
488
connect( m_model, SIGNAL( rowsAboutToBeInserted( QModelIndex, int, int ) ),
489
SLOT( slotRowsAboutToBeInserted( QModelIndex, int, int ) ) );
490
connect( m_model, SIGNAL( rowsInserted( QModelIndex, int, int ) ),
491
SLOT( slotRowsInserted( QModelIndex, int, int ) ) );
492
connect( m_model, SIGNAL( rowsAboutToBeRemoved( QModelIndex, int, int ) ),
493
SLOT( slotRowsAboutToBeRemoved( QModelIndex, int, int ) ) );
494
connect( m_model, SIGNAL( rowsRemoved( QModelIndex, int, int ) ),
495
SLOT( slotRowsRemoved( QModelIndex, int, int ) ) );
496
connect( m_model, SIGNAL( columnsAboutToBeInserted( QModelIndex, int, int ) ),
497
SLOT( slotColumnsAboutToBeInserted( QModelIndex, int, int ) ) );
498
connect( m_model, SIGNAL( columnsInserted( QModelIndex, int, int ) ),
499
SLOT( slotColumnsInserted( QModelIndex, int, int ) ) );
500
connect( m_model, SIGNAL( columnsRemoved( QModelIndex, int, int ) ),
501
SLOT( slotColumnsRemoved( QModelIndex, int, int ) ) );
502
connect( m_model, SIGNAL( columnsAboutToBeRemoved( QModelIndex, int, int ) ),
503
SLOT( slotColumnsAboutToBeRemoved( QModelIndex, int, int ) ) );
504
connect( m_model, SIGNAL( modelReset() ),
505
this, SLOT( rebuildCache() ) );
508
calculateSampleStepWidth();
511
void CartesianDiagramDataCompressor::setRootIndex( const QModelIndex& root )
513
if ( m_rootIndex != root ) {
514
Q_ASSERT( root.model() == m_model || !root.isValid() );
516
m_modelCache.setRootIndex( root );
518
calculateSampleStepWidth();
521
void CartesianDiagramDataCompressor::setResolution( int x, int y )
523
const int oldX = m_xResolution;
524
const int oldY = m_yResolution;
526
if( m_datasetDimension != 1 )
528
// just ignore the resolution in that case
529
m_xResolution = m_model == 0 ? 0 : m_model->rowCount( m_rootIndex );
530
m_yResolution = qMax( 0, y );
532
else if ( x != m_xResolution || y != m_yResolution ) {
533
m_xResolution = qMax( 0, x );
534
m_yResolution = qMax( 0, y );
536
calculateSampleStepWidth();
539
if( oldX != m_xResolution || oldY != m_yResolution )
542
calculateSampleStepWidth();
546
void CartesianDiagramDataCompressor::clearCache()
548
for ( int column = 0; column < m_data.size(); ++column )
549
m_data[column].fill( DataPoint() );
552
void CartesianDiagramDataCompressor::rebuildCache() const
554
Q_ASSERT( m_datasetDimension != 0 );
557
const int columnCount = m_model ? m_model->columnCount( m_rootIndex ) / m_datasetDimension : 0;
558
const int rowCount = qMin( m_model ? m_model->rowCount( m_rootIndex ) : 0, m_xResolution );
559
m_data.resize( columnCount );
560
for ( int i = 0; i < columnCount; ++i ) {
561
m_data[i].resize( rowCount );
563
// also empty the attrs cache
564
m_dataValueAttributesCache.clear();
567
const CartesianDiagramDataCompressor::DataPoint& CartesianDiagramDataCompressor::data( const CachePosition& position ) const
569
static DataPoint NullDataPoint;
570
if ( ! isValidCachePosition( position ) ) return NullDataPoint;
571
if ( ! isCached( position ) ) retrieveModelData( position );
572
return m_data[ position.second ][ position.first ];
575
void CartesianDiagramDataCompressor::retrieveModelData( const CachePosition& position ) const
577
Q_ASSERT( isValidCachePosition( position ) );
583
bool forceHidden = false;
584
result.hidden = true;
585
const QModelIndexList indexes = mapToModel( position );
586
if( m_datasetDimension != 1 )
588
Q_ASSERT( indexes.count() == 2 );
589
const QModelIndex xIndex = indexes.first();
590
const QModelIndex yIndex = indexes.last();
591
const double xData = m_modelCache.data( xIndex );
592
const double yData = m_modelCache.data( yIndex );
593
result.index = xIndex;
595
result.value = yData;
599
if ( ! indexes.isEmpty() ) {
600
result.value = std::numeric_limits< double >::quiet_NaN();
602
Q_FOREACH( const QModelIndex& index, indexes ) {
603
const double value = m_modelCache.data( index );
604
if( !ISNAN( value ) )
606
result.value = ISNAN( result.value ) ? value : result.value + value;
608
result.key += index.row();
610
result.index = indexes.at( 0 );
611
result.key /= indexes.size();
612
result.value /= indexes.size();
617
Q_FOREACH( const QModelIndex& index, indexes )
619
// the point is visible if any of the points at this pixel position is visible
620
if ( qVariantValue<bool>( m_model->data( index, DataHiddenRole ) ) == false ) {
621
result.hidden = false;
634
m_data[position.second][position.first] = result;
635
Q_ASSERT( isCached( position ) );
638
CartesianDiagramDataCompressor::CachePosition CartesianDiagramDataCompressor::mapToCache(
639
const QModelIndex& index ) const
641
Q_ASSERT( m_datasetDimension != 0 );
643
static const CachePosition NullPosition( -1, -1 );
644
if ( ! index.isValid() ) return NullPosition;
645
return mapToCache( index.row(), index.column() );
648
CartesianDiagramDataCompressor::CachePosition CartesianDiagramDataCompressor::mapToCache(
649
int row, int column ) const
651
Q_ASSERT( m_datasetDimension != 0 );
653
if ( m_data.size() == 0 || m_data[0].size() == 0 ) return mapToCache( QModelIndex() );
654
// assumption: indexes per column == 1
655
if ( indexesPerPixel() == 0 ) return mapToCache( QModelIndex() );
656
return CachePosition( static_cast< int >( ( row ) / indexesPerPixel() ), column / m_datasetDimension );
659
QModelIndexList CartesianDiagramDataCompressor::mapToModel( const CachePosition& position ) const
661
if ( isValidCachePosition( position ) ) {
662
QModelIndexList indexes;
663
if( m_datasetDimension == 2 )
665
indexes << m_model->index( position.first, position.second * 2, m_rootIndex );
666
indexes << m_model->index( position.first, position.second * 2 + 1, m_rootIndex );
670
// assumption: indexes per column == 1
671
const qreal ipp = indexesPerPixel();
672
for ( int i = 0; i < ipp; ++i ) {
673
const QModelIndex index = m_model->index( qRound( position.first * ipp ) + i, position.second, m_rootIndex );
674
if( index.isValid() )
680
return QModelIndexList();
684
qreal CartesianDiagramDataCompressor::indexesPerPixel() const
686
if ( m_data.size() == 0 ) return 0;
687
if ( m_data[0].size() == 0 ) return 0;
688
if ( ! m_model ) return 0;
689
return static_cast< qreal >( m_model->rowCount( m_rootIndex ) ) / static_cast< qreal >( m_data[0].size() );
692
bool CartesianDiagramDataCompressor::isValidCachePosition( const CachePosition& position ) const
694
if ( ! m_model ) return false;
695
if ( m_data.size() == 0 || m_data[0].size() == 0 ) return false;
696
if ( position.second < 0 || position.second >= m_data.size() ) return false;
697
if ( position.first < 0 || position.first >= m_data[0].size() ) return false;
701
void CartesianDiagramDataCompressor::invalidate( const CachePosition& position )
703
if ( isValidCachePosition( position ) ) {
704
m_data[position.second][position.first] = DataPoint();
705
// Also invalidate the data value attributes at "position".
706
// Otherwise the user overwrites the attributes without us noticing
707
// it because we keep reading what's in the cache.
708
m_dataValueAttributesCache.remove( position );
712
bool CartesianDiagramDataCompressor::isCached( const CachePosition& position ) const
714
Q_ASSERT( isValidCachePosition( position ) );
715
const DataPoint& p = m_data[position.second][position.first];
716
return p.index.isValid();
719
void CartesianDiagramDataCompressor::calculateSampleStepWidth()
721
if ( m_mode == Precise ) {
726
static unsigned int SomePrimes[] = {
727
2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47,
728
53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101,
729
151, 211, 313, 401, 503, 607, 701, 811, 911, 1009,
730
10037, 12911, 16001, 20011, 50021,
731
100003, 137867, 199999, 500009, 707753, 1000003, 0
732
}; // ... after that, having a model at all becomes impractical
734
// we want at least 17 samples per data point, using a prime step width
735
const double WantedSamples = 17;
736
if ( WantedSamples > indexesPerPixel() ) {
740
for ( i = 0; SomePrimes[i] != 0; ++i ) {
741
if ( WantedSamples * SomePrimes[i+1] > indexesPerPixel() ) {
745
m_sampleStep = SomePrimes[i];
746
if ( SomePrimes[i] == 0 ) {
747
m_sampleStep = SomePrimes[i-1];
749
m_sampleStep = SomePrimes[i];
754
void CartesianDiagramDataCompressor::setDatasetDimension( int dimension )
756
if ( dimension != m_datasetDimension ) {
757
m_datasetDimension = dimension;
759
calculateSampleStepWidth();