00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include <limits>
00031
00032 #include <QAbstractItemModel>
00033
00034 #include "KDChartBarDiagram.h"
00035 #include "KDChartLineDiagram.h"
00036 #include "KDChartTextAttributes.h"
00037 #include "KDChartAttributesModel.h"
00038 #include "KDChartAbstractCartesianDiagram.h"
00039 #include "KDChartNormalLineDiagram_p.h"
00040
00041 using namespace KDChart;
00042 using namespace std;
00043
00044 NormalLineDiagram::NormalLineDiagram( LineDiagram* d )
00045 : LineDiagramType( d )
00046 {
00047 }
00048
00049 LineDiagram::LineType NormalLineDiagram::type() const
00050 {
00051 return LineDiagram::Normal;
00052 }
00053
00054 const QPair< QPointF, QPointF > NormalLineDiagram::calculateDataBoundaries() const
00055 {
00056 const int rowCount = compressor().modelDataRows();
00057 const int colCount = compressor().modelDataColumns();
00058 const double xMin = 0.0;
00059 double xMax = diagram()->model() ? diagram()->model()->rowCount( diagram()->rootIndex() ) : 0;
00060 if ( !diagram()->centerDataPoints() && diagram()->model() )
00061 xMax -= 1;
00062 double yMin = std::numeric_limits< double >::quiet_NaN();
00063 double yMax = std::numeric_limits< double >::quiet_NaN();
00064
00065 for( int column = 0; column < colCount; ++column )
00066 {
00067 for ( int row = 0; row < rowCount; ++row )
00068 {
00069 const CartesianDiagramDataCompressor::CachePosition position( row, column );
00070 const CartesianDiagramDataCompressor::DataPoint point = compressor().data( position );
00071 const double value = ISNAN( point.value ) ? 0.0 : point.value;
00072
00073 if ( ISNAN( yMin ) ) {
00074 yMin = value;
00075 yMax = value;
00076 } else {
00077 yMin = qMin( yMin, value );
00078 yMax = qMax( yMax, value );
00079 }
00080 }
00081 }
00082
00083
00084
00085
00086 const QPointF bottomLeft( QPointF( xMin, yMin ) );
00087 const QPointF topRight( QPointF( xMax, yMax ) );
00088 return QPair< QPointF, QPointF >( bottomLeft, topRight );
00089 }
00090
00091 void NormalLineDiagram::paint( PaintContext* ctx )
00092 {
00093 reverseMapper().clear();
00094 Q_ASSERT( dynamic_cast<CartesianCoordinatePlane*>( ctx->coordinatePlane() ) );
00095 CartesianCoordinatePlane* plane = static_cast<CartesianCoordinatePlane*>( ctx->coordinatePlane() );
00096 const int columnCount = compressor().modelDataColumns();
00097 const int rowCount = compressor().modelDataRows();
00098 if ( columnCount == 0 || rowCount == 0 ) return;
00099
00100
00101
00102 int maxFound = 0;
00103
00104
00105
00106
00107
00108
00109
00110 maxFound = columnCount;
00111
00112
00113 for( int column = 0; column < columnCount; ++column ) {
00114 DataValueTextInfoList textInfoList;
00115 LineAttributesInfoList lineList;
00116 LineAttributes laPreviousCell;
00117 CartesianDiagramDataCompressor::DataPoint lastPoint;
00118 qreal lastAreaBoundingValue;
00119
00120
00121 const qreal minYValue = plane->visibleDataRange().bottom();
00122
00123 CartesianDiagramDataCompressor::CachePosition previousCellPosition;
00124 for ( int row = 0; row < rowCount; ++row ) {
00125 const CartesianDiagramDataCompressor::CachePosition position( row, column );
00126
00127 CartesianDiagramDataCompressor::DataPoint point = compressor().data( position );
00128
00129 const QModelIndex sourceIndex = attributesModel()->mapToSource( point.index );
00130
00131 const LineAttributes laCell = diagram()->lineAttributes( sourceIndex );
00132 const LineAttributes::MissingValuesPolicy policy = laCell.missingValuesPolicy();
00133
00134
00135 qreal areaBoundingValue;
00136 if ( laCell.areaBoundingDataset() != -1 ) {
00137 const CartesianDiagramDataCompressor::CachePosition areaBoundingCachePosition( row, laCell.areaBoundingDataset() );
00138 areaBoundingValue = compressor().data( areaBoundingCachePosition ).value;
00139 } else
00140
00141 areaBoundingValue = minYValue;
00142
00143 if( ISNAN( point.value ) )
00144 {
00145 switch( policy )
00146 {
00147 case LineAttributes::MissingValuesAreBridged:
00148
00149 continue;
00150 case LineAttributes::MissingValuesShownAsZero:
00151
00152 point.value = 0.0;
00153 break;
00154 case LineAttributes::MissingValuesHideSegments:
00155
00156 break;
00157 default:
00158 break;
00159
00160 }
00161 }
00162
00163
00164 const QPointF a( plane->translate( QPointF( diagram()->centerDataPoints() ? lastPoint.key + 0.5 : lastPoint.key, lastPoint.value ) ) );
00165 const QPointF b( plane->translate( QPointF( diagram()->centerDataPoints() ? point.key + 0.5 : point.key, point.value ) ) );
00166 const QPointF c( plane->translate( QPointF( diagram()->centerDataPoints() ? lastPoint.key + 0.5 : lastPoint.key, lastAreaBoundingValue ) ) );
00167 const QPointF d( plane->translate( QPointF( diagram()->centerDataPoints() ? point.key + 0.5 : point.key, areaBoundingValue ) ) );
00168
00169
00170 const PositionPoints pts = PositionPoints( b, a, d, c );
00171
00172 QList<QPolygonF> areas;
00173 if ( !ISNAN( point.value ) && !ISNAN( lastPoint.value ) && laCell.displayArea() ) {
00174 areas << ( QPolygonF() << a << b << d << c );
00175 }
00176
00177 if ( ! point.hidden && !ISNAN( point.value ) )
00178 {
00179 appendDataValueTextInfoToList( diagram(), textInfoList, sourceIndex, &position,
00180 pts, Position::NorthWest, Position::SouthWest,
00181 point.value );
00182 paintAreas( ctx, attributesModel()->mapToSource( lastPoint.index ), areas, laCell.transparency() );
00183
00184 if( row > 0 && !ISNAN( lastPoint.value ) )
00185 lineList.append( LineAttributesInfo( sourceIndex, a, b ) );
00186 }
00187
00188
00189 previousCellPosition = position;
00190 laPreviousCell = laCell;
00191 lastAreaBoundingValue = areaBoundingValue;
00192 lastPoint = point;
00193 }
00194
00195 LineAttributes::MissingValuesPolicy policy = LineAttributes::MissingValuesAreBridged;
00196 paintElements( ctx, textInfoList, lineList, policy );
00197 }
00198 }