KDChartPercentLineDiagram_p.cpp

Go to the documentation of this file.
00001 /* -*- Mode: C++ -*-
00002    KDChart - a multi-platform charting engine
00003    */
00004 
00005 /****************************************************************************
00006  ** Copyright (C) 2005-2007 Klarälvdalens Datakonsult AB.  All rights reserved.
00007  **
00008  ** This file is part of the KD Chart library.
00009  **
00010  ** This file may be distributed and/or modified under the terms of the
00011  ** GNU General Public License version 2 as published by the Free Software
00012  ** Foundation and appearing in the file LICENSE.GPL included in the
00013  ** packaging of this file.
00014  **
00015  ** Licensees holding valid commercial KD Chart licenses may use this file in
00016  ** accordance with the KD Chart Commercial License Agreement provided with
00017  ** the Software.
00018  **
00019  ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00020  ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00021  **
00022  ** See http://www.kdab.net/kdchart for
00023  **   information about KD Chart Commercial License Agreements.
00024  **
00025  ** Contact info@kdab.net if any conditions of this
00026  ** licensing are not clear to you.
00027  **
00028  **********************************************************************/
00029 
00030 #include "KDChartPercentLineDiagram_p.h"
00031 
00032 #include <QModelIndex>
00033 
00034 #include "KDChartBarDiagram.h"
00035 #include "KDChartLineDiagram.h"
00036 #include "KDChartTextAttributes.h"
00037 #include "KDChartAttributesModel.h"
00038 #include "KDChartAbstractCartesianDiagram.h"
00039 
00040 using namespace KDChart;
00041 using namespace std;
00042 
00043 PercentLineDiagram::PercentLineDiagram( LineDiagram* d )
00044     : LineDiagramType( d )
00045 {
00046 }
00047 
00048 LineDiagram::LineType PercentLineDiagram::type() const
00049 {
00050     return LineDiagram::Percent;
00051 }
00052 
00053 const QPair<QPointF, QPointF> PercentLineDiagram::calculateDataBoundaries() const
00054 {
00055     const double xMin = 0.0;
00056     double xMax = diagram()->model() ? diagram()->model()->rowCount( diagram()->rootIndex() ) : 0;
00057     if ( !diagram()->centerDataPoints() && diagram()->model() )
00058         xMax -= 1;
00059     const double yMin = 0.0;
00060     const double yMax = 100.0;
00061 
00062     QPointF bottomLeft( QPointF( xMin, yMin ) );
00063     QPointF topRight( QPointF( xMax, yMax ) );
00064     return QPair<QPointF, QPointF> ( bottomLeft, topRight );
00065 }
00066 
00067 void PercentLineDiagram::paint(  PaintContext* ctx )
00068 {
00069     reverseMapper().clear();
00070 
00071     const QPair<QPointF, QPointF> boundaries = diagram()->dataBoundaries();
00072     const QPointF bottomLeft = boundaries.first;
00073     const QPointF topRight = boundaries.second;
00074 
00075     const int columnCount = compressor().modelDataColumns();
00076     const int rowCount = compressor().modelDataRows();
00077 
00078 // FIXME integrade column index retrieval to compressor:
00079     int maxFound = 0;
00080 //    {   // find the last column number that is not hidden
00081 //        for( int iColumn =  datasetDimension() - 1;
00082 //             iColumn <  columnCount;
00083 //             iColumn += datasetDimension() )
00084 //            if( ! diagram()->isHidden( iColumn ) )
00085 //                maxFound = iColumn;
00086 //    }
00087     maxFound = columnCount;
00088     // ^^^ temp
00089     const int lastVisibleColumn = maxFound - 1;
00090 
00091     DataValueTextInfoList list;
00092     LineAttributesInfoList lineList;
00093     LineAttributes::MissingValuesPolicy policy;
00094 
00095     //FIXME(khz): add LineAttributes::MissingValuesPolicy support for LineDiagram::Stacked and ::Percent
00096 
00097     double maxValue = 100; // always 100%
00098     double sumValues = 0;
00099     QVector <double > percentSumValues;
00100 
00101     //calculate sum of values for each column and store
00102     for ( int row = 0; row < rowCount; ++row )
00103     {
00104         for( int col = 0; col < columnCount; ++col )
00105         {
00106             const CartesianDiagramDataCompressor::CachePosition position( row, col );
00107             CartesianDiagramDataCompressor::DataPoint point = compressor().data( position );
00108             const QModelIndex sourceIndex = attributesModel()->mapToSource( point.index );
00109             const LineAttributes laCell = diagram()->lineAttributes( sourceIndex );
00110             const LineAttributes::MissingValuesPolicy policy = laCell.missingValuesPolicy();
00111             if( ISNAN( point.value ) && policy == LineAttributes::MissingValuesAreBridged )
00112                 point.value = interpolateMissingValue( position );
00113             if ( point.value > 0 )
00114                 sumValues += point.value;
00115             if ( col == lastVisibleColumn )
00116             {
00117                 percentSumValues << sumValues ;
00118                 sumValues = 0;
00119             }
00120         }
00121     }
00122 
00123     QList<QPointF> bottomPoints;
00124     bool bFirstDataset = true;
00125 
00126     for( int column = 0; column < columnCount; ++column )
00127     {
00128         //display area can be set by dataset ( == column) and/or by cell
00129         LineAttributes laPreviousCell; // by default no area is drawn
00130         QModelIndex indexPreviousCell;
00131         QList<QPolygonF> areas;
00132         QList<QPointF> points;
00133 
00134         for( int row = 0; row < rowCount; ++row )
00135         {
00136             const CartesianDiagramDataCompressor::CachePosition position( row, column );
00137             CartesianDiagramDataCompressor::DataPoint point = compressor().data( position );
00138             const QModelIndex sourceIndex = attributesModel()->mapToSource( point.index );
00139             const LineAttributes laCell = diagram()->lineAttributes( sourceIndex );
00140             const bool bDisplayCellArea = laCell.displayArea();
00141 
00142             double stackedValues = 0, nextValues = 0, nextKey = 0;
00143             for ( int column2 = column;
00144                   column2 >= 0;//datasetDimension() - 1;
00145                   column2 -= 1 )//datasetDimension() )
00146             {
00147                 const CartesianDiagramDataCompressor::CachePosition position( row, column2 );
00148                 CartesianDiagramDataCompressor::DataPoint point = compressor().data( position );
00149 
00150                 const QModelIndex sourceIndex = attributesModel()->mapToSource( point.index );
00151                 const LineAttributes::MissingValuesPolicy policy = laCell.missingValuesPolicy();
00152                 if( ISNAN( point.value ) && policy == LineAttributes::MissingValuesAreBridged )
00153                     point.value = interpolateMissingValue( position );
00154 
00155                 const double val = point.value;
00156                 if( val > 0 )
00157                     stackedValues += val;
00158                 //qDebug() << valueForCell( iRow, iColumn2 );
00159                 if ( row + 1 < rowCount ){
00160                     const CartesianDiagramDataCompressor::CachePosition position( row + 1, column2 );
00161                     CartesianDiagramDataCompressor::DataPoint point = compressor().data( position );
00162 
00163                     const QModelIndex sourceIndex = attributesModel()->mapToSource( point.index );
00164                     const LineAttributes::MissingValuesPolicy policy = laCell.missingValuesPolicy();
00165                     if( ISNAN( point.value ) && policy == LineAttributes::MissingValuesAreBridged )
00166                         point.value = interpolateMissingValue( position );
00167 
00168                     const double val = point.value;
00169                     if( val > 0 )
00170                         nextValues += val;
00171                     nextKey = point.key;
00172                 }
00173             }
00174             if ( percentSumValues.at( row ) != 0  )
00175                 stackedValues = stackedValues / percentSumValues.at( row ) * maxValue;
00176             else
00177                 stackedValues = 0.0;
00178             //qDebug() << stackedValues << endl;
00179             QPointF nextPoint = ctx->coordinatePlane()->translate( QPointF( diagram()->centerDataPoints() ? point.key + 0.5 : point.key, stackedValues ) );
00180             points << nextPoint;
00181 
00182             const QPointF ptNorthWest( nextPoint );
00183             const QPointF ptSouthWest(
00184                 bDisplayCellArea
00185                 ? ( bFirstDataset
00186                     ? ctx->coordinatePlane()->translate( QPointF( diagram()->centerDataPoints() ? point.key + 0.5 : point.key, 0.0 ) )
00187                     : bottomPoints.at( row )
00188                     )
00189                 : nextPoint );
00190             QPointF ptNorthEast;
00191             QPointF ptSouthEast;
00192 
00193             if ( row + 1 < rowCount ){
00194                  if ( percentSumValues.at( row + 1 ) != 0  )
00195                      nextValues = nextValues / percentSumValues.at( row + 1 ) * maxValue;
00196                  else
00197                      nextValues = 0.0;
00198                 QPointF toPoint = ctx->coordinatePlane()->translate( QPointF( diagram()->centerDataPoints() ? nextKey + 0.5 : nextKey, nextValues ) );
00199                 lineList.append( LineAttributesInfo( sourceIndex, nextPoint, toPoint ) );
00200                 ptNorthEast = toPoint;
00201                 ptSouthEast =
00202                     bDisplayCellArea
00203                     ? ( bFirstDataset
00204                         ? ctx->coordinatePlane()->translate( QPointF( diagram()->centerDataPoints() ? nextKey + 0.5 : nextKey, 0.0 ) )
00205                         : bottomPoints.at( row + 1 )
00206                         )
00207                     : toPoint;
00208                 if( areas.count() && laCell != laPreviousCell ){
00209                     paintAreas( ctx, indexPreviousCell, areas, laPreviousCell.transparency() );
00210                     areas.clear();
00211                 }
00212                 if( bDisplayCellArea ){
00213                     QPolygonF poly;
00214                     poly << ptNorthWest << ptNorthEast << ptSouthEast << ptSouthWest;
00215                     areas << poly;
00216                     laPreviousCell = laCell;
00217                     indexPreviousCell = sourceIndex;
00218                 }else{
00219                     //qDebug() << "no area shown for row"<<iRow<<"  column"<<iColumn;
00220                 }
00221             }else{
00222                 ptNorthEast = ptNorthWest;
00223                 ptSouthEast = ptSouthWest;
00224             }
00225 
00226             if( !ISNAN( point.value ) )
00227             {
00228                 const PositionPoints pts( ptNorthWest, ptNorthEast, ptSouthEast, ptSouthWest );
00229                 appendDataValueTextInfoToList( diagram(), list, sourceIndex, &position,
00230                                                pts, Position::NorthWest, Position::SouthWest,
00231                                                point.value );
00232             }
00233         }
00234         if( areas.count() ){
00235             paintAreas( ctx, indexPreviousCell, areas, laPreviousCell.transparency() );
00236             areas.clear();
00237         }
00238         bottomPoints = points;
00239         bFirstDataset = false;
00240     }
00241     paintElements( ctx, list, lineList, policy );
00242 }

Generated on Thu Mar 4 23:19:12 2010 for KD Chart 2 by  doxygen 1.5.4