KDChartPercentLineDiagram_p.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "KDChartPercentLineDiagram_p.h"
00024
00025 #include <QModelIndex>
00026
00027 #include "KDChartBarDiagram.h"
00028 #include "KDChartLineDiagram.h"
00029 #include "KDChartTextAttributes.h"
00030 #include "KDChartAttributesModel.h"
00031 #include "KDChartAbstractCartesianDiagram.h"
00032
00033 using namespace KDChart;
00034 using namespace std;
00035
00036 PercentLineDiagram::PercentLineDiagram( LineDiagram* d )
00037 : LineDiagramType( d )
00038 {
00039 }
00040
00041 LineDiagram::LineType PercentLineDiagram::type() const
00042 {
00043 return LineDiagram::Percent;
00044 }
00045
00046 const QPair<QPointF, QPointF> PercentLineDiagram::calculateDataBoundaries() const
00047 {
00048 const double xMin = 0.0;
00049 double xMax = diagram()->model() ? diagram()->model()->rowCount( diagram()->rootIndex() ) : 0;
00050 if ( !diagram()->centerDataPoints() && diagram()->model() )
00051 xMax -= 1;
00052 const double yMin = 0.0;
00053 const double yMax = 100.0;
00054
00055 QPointF bottomLeft( QPointF( xMin, yMin ) );
00056 QPointF topRight( QPointF( xMax, yMax ) );
00057 return QPair<QPointF, QPointF> ( bottomLeft, topRight );
00058 }
00059
00060 void PercentLineDiagram::paint( PaintContext* ctx )
00061 {
00062 reverseMapper().clear();
00063
00064 const QPair<QPointF, QPointF> boundaries = diagram()->dataBoundaries();
00065 const QPointF bottomLeft = boundaries.first;
00066 const QPointF topRight = boundaries.second;
00067
00068 const int columnCount = compressor().modelDataColumns();
00069 const int rowCount = compressor().modelDataRows();
00070
00071
00072 int maxFound = 0;
00073
00074
00075
00076
00077
00078
00079
00080 maxFound = columnCount;
00081
00082 const int lastVisibleColumn = maxFound - 1;
00083
00084 DataValueTextInfoList list;
00085 LineAttributesInfoList lineList;
00086 LineAttributes::MissingValuesPolicy policy = LineAttributes::MissingValuesAreBridged;
00087
00088
00089
00090 double maxValue = 100;
00091 double sumValues = 0;
00092 QVector <double > percentSumValues;
00093
00094
00095 for ( int row = 0; row < rowCount; ++row )
00096 {
00097 for( int col = 0; col < columnCount; ++col )
00098 {
00099 const CartesianDiagramDataCompressor::CachePosition position( row, col );
00100 CartesianDiagramDataCompressor::DataPoint point = compressor().data( position );
00101 const QModelIndex sourceIndex = attributesModel()->mapToSource( point.index );
00102 const LineAttributes laCell = diagram()->lineAttributes( sourceIndex );
00103 const LineAttributes::MissingValuesPolicy policy = laCell.missingValuesPolicy();
00104 if( ISNAN( point.value ) && policy == LineAttributes::MissingValuesAreBridged )
00105 point.value = interpolateMissingValue( position );
00106 if ( point.value > 0 )
00107 sumValues += point.value;
00108 if ( col == lastVisibleColumn )
00109 {
00110 percentSumValues << sumValues ;
00111 sumValues = 0;
00112 }
00113 }
00114 }
00115
00116 QList<QPointF> bottomPoints;
00117 bool bFirstDataset = true;
00118
00119 for( int column = 0; column < columnCount; ++column )
00120 {
00121
00122 LineAttributes laPreviousCell;
00123 QModelIndex indexPreviousCell;
00124 QList<QPolygonF> areas;
00125 QList<QPointF> points;
00126
00127 for( int row = 0; row < rowCount; ++row )
00128 {
00129 const CartesianDiagramDataCompressor::CachePosition position( row, column );
00130 CartesianDiagramDataCompressor::DataPoint point = compressor().data( position );
00131 const QModelIndex sourceIndex = attributesModel()->mapToSource( point.index );
00132 const LineAttributes laCell = diagram()->lineAttributes( sourceIndex );
00133 const bool bDisplayCellArea = laCell.displayArea();
00134
00135 double stackedValues = 0, nextValues = 0, nextKey = 0;
00136 for ( int column2 = column;
00137 column2 >= 0;
00138 column2 -= 1 )
00139 {
00140 const CartesianDiagramDataCompressor::CachePosition position( row, column2 );
00141 CartesianDiagramDataCompressor::DataPoint point = compressor().data( position );
00142
00143 const QModelIndex sourceIndex = attributesModel()->mapToSource( point.index );
00144 const LineAttributes::MissingValuesPolicy policy = laCell.missingValuesPolicy();
00145 if( ISNAN( point.value ) && policy == LineAttributes::MissingValuesAreBridged )
00146 point.value = interpolateMissingValue( position );
00147
00148 const double val = point.value;
00149 if( val > 0 )
00150 stackedValues += val;
00151
00152 if ( row + 1 < rowCount ){
00153 const CartesianDiagramDataCompressor::CachePosition position( row + 1, column2 );
00154 CartesianDiagramDataCompressor::DataPoint point = compressor().data( position );
00155
00156 const QModelIndex sourceIndex = attributesModel()->mapToSource( point.index );
00157 const LineAttributes::MissingValuesPolicy policy = laCell.missingValuesPolicy();
00158 if( ISNAN( point.value ) && policy == LineAttributes::MissingValuesAreBridged )
00159 point.value = interpolateMissingValue( position );
00160
00161 const double val = point.value;
00162 if( val > 0 )
00163 nextValues += val;
00164 nextKey = point.key;
00165 }
00166 }
00167 if ( percentSumValues.at( row ) != 0 )
00168 stackedValues = stackedValues / percentSumValues.at( row ) * maxValue;
00169 else
00170 stackedValues = 0.0;
00171
00172 QPointF nextPoint = ctx->coordinatePlane()->translate( QPointF( diagram()->centerDataPoints() ? point.key + 0.5 : point.key, stackedValues ) );
00173 points << nextPoint;
00174
00175 const QPointF ptNorthWest( nextPoint );
00176 const QPointF ptSouthWest(
00177 bDisplayCellArea
00178 ? ( bFirstDataset
00179 ? ctx->coordinatePlane()->translate( QPointF( diagram()->centerDataPoints() ? point.key + 0.5 : point.key, 0.0 ) )
00180 : bottomPoints.at( row )
00181 )
00182 : nextPoint );
00183 QPointF ptNorthEast;
00184 QPointF ptSouthEast;
00185
00186 if ( row + 1 < rowCount ){
00187 if ( percentSumValues.at( row + 1 ) != 0 )
00188 nextValues = nextValues / percentSumValues.at( row + 1 ) * maxValue;
00189 else
00190 nextValues = 0.0;
00191 QPointF toPoint = ctx->coordinatePlane()->translate( QPointF( diagram()->centerDataPoints() ? nextKey + 0.5 : nextKey, nextValues ) );
00192 lineList.append( LineAttributesInfo( sourceIndex, nextPoint, toPoint ) );
00193 ptNorthEast = toPoint;
00194 ptSouthEast =
00195 bDisplayCellArea
00196 ? ( bFirstDataset
00197 ? ctx->coordinatePlane()->translate( QPointF( diagram()->centerDataPoints() ? nextKey + 0.5 : nextKey, 0.0 ) )
00198 : bottomPoints.at( row + 1 )
00199 )
00200 : toPoint;
00201 if( areas.count() && laCell != laPreviousCell ){
00202 paintAreas( ctx, indexPreviousCell, areas, laPreviousCell.transparency() );
00203 areas.clear();
00204 }
00205 if( bDisplayCellArea ){
00206 QPolygonF poly;
00207 poly << ptNorthWest << ptNorthEast << ptSouthEast << ptSouthWest;
00208 areas << poly;
00209 laPreviousCell = laCell;
00210 indexPreviousCell = sourceIndex;
00211 }else{
00212
00213 }
00214 }else{
00215 ptNorthEast = ptNorthWest;
00216 ptSouthEast = ptSouthWest;
00217 }
00218
00219 if( !ISNAN( point.value ) )
00220 {
00221 const PositionPoints pts( ptNorthWest, ptNorthEast, ptSouthEast, ptSouthWest );
00222 appendDataValueTextInfoToList( diagram(), list, sourceIndex, &position,
00223 pts, Position::NorthWest, Position::SouthWest,
00224 point.value );
00225 }
00226 }
00227 if( areas.count() ){
00228 paintAreas( ctx, indexPreviousCell, areas, laPreviousCell.transparency() );
00229 areas.clear();
00230 }
00231 bottomPoints = points;
00232 bFirstDataset = false;
00233 }
00234 paintElements( ctx, list, lineList, policy );
00235 }