KDChartNormalPlotter_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 "KDChartNormalPlotter_p.h"
00031 #include "KDChartPlotter.h"
00032 
00033 #include <limits>
00034 
00035 using namespace KDChart;
00036 using namespace std;
00037 
00038 NormalPlotter::NormalPlotter( Plotter* d )
00039     : PlotterType( d )
00040 {
00041 }
00042 
00043 Plotter::PlotType NormalPlotter::type() const
00044 {
00045     return Plotter::Normal;
00046 }
00047 
00048 const QPair< QPointF, QPointF > NormalPlotter::calculateDataBoundaries() const
00049 {
00050     const int rowCount = compressor().modelDataRows();
00051     const int colCount = compressor().modelDataColumns();
00052     double xMin = std::numeric_limits< double >::quiet_NaN();
00053     double xMax = std::numeric_limits< double >::quiet_NaN();
00054     double yMin = std::numeric_limits< double >::quiet_NaN();
00055     double yMax = std::numeric_limits< double >::quiet_NaN();
00056 
00057     for( int column = 0; column < colCount; ++column )
00058     {
00059         for ( int row = 0; row < rowCount; ++row )
00060         {
00061             const CartesianDiagramDataCompressor::CachePosition position( row, column );
00062             const CartesianDiagramDataCompressor::DataPoint point = compressor().data( position );
00063 
00064             const double valueX = ISNAN( point.key ) ? 0.0 : point.key;
00065             const double valueY = ISNAN( point.value ) ? 0.0 : point.value;
00066 
00067             if( ISNAN( xMin ) )
00068             {
00069                 xMin = valueX;
00070                 xMax = valueX;
00071                 yMin = valueY;
00072                 yMax = valueY;
00073             }
00074             else
00075             {
00076                 xMin = qMin( xMin, valueX );
00077                 xMax = qMax( xMax, valueX );
00078                 yMin = qMin( yMin, valueY );
00079                 yMax = qMax( yMax, valueY );
00080             }
00081         }
00082     }
00083 
00084     // NOTE: calculateDataBoundaries must return the *real* data boundaries!
00085     //       i.e. we may NOT fake yMin to be qMin( 0.0, yMin )
00086     //       (khz, 2008-01-24)
00087     const QPointF bottomLeft( QPointF( xMin, yMin ) );
00088     const QPointF topRight( QPointF( xMax, yMax ) );
00089     return QPair< QPointF, QPointF >( bottomLeft, topRight );
00090 }
00091 
00092 void NormalPlotter::paint( PaintContext* ctx )
00093 {
00094     reverseMapper().clear();
00095 
00096     Q_ASSERT( dynamic_cast< CartesianCoordinatePlane* >( ctx->coordinatePlane() ) );
00097     const CartesianCoordinatePlane* const plane = static_cast< CartesianCoordinatePlane* >( ctx->coordinatePlane() );
00098     const int colCount = compressor().modelDataColumns();
00099     const int rowCount = compressor().modelDataRows();
00100 
00101     if( colCount == 0 || rowCount == 0 )
00102         return;
00103 
00104     DataValueTextInfoList textInfoList;
00105 
00106     for( int column = 0; column < colCount; ++column )
00107     {
00108         LineAttributesInfoList lineList;
00109         LineAttributes laPreviousCell;
00110         CartesianDiagramDataCompressor::CachePosition previousCellPosition;
00111 
00112         for( int row = 0; row < rowCount; ++row )
00113         {
00114             const CartesianDiagramDataCompressor::CachePosition position( row, column );
00115             const CartesianDiagramDataCompressor::DataPoint point = compressor().data( position );
00116 
00117             const QModelIndex sourceIndex = attributesModel()->mapToSource( point.index );
00118             LineAttributes laCell = diagram()->lineAttributes( sourceIndex );
00119             const LineAttributes::MissingValuesPolicy policy = laCell.missingValuesPolicy();
00120 
00121             if( ISNAN( point.key ) || ISNAN( point.value ) )
00122             {
00123                 switch( policy )
00124                 {
00125                 case LineAttributes::MissingValuesAreBridged: // we just bridge both values
00126                     continue;
00127                 case LineAttributes::MissingValuesShownAsZero: // fall-through since that attribute makes no sense for the plotter
00128                 case LineAttributes::MissingValuesHideSegments: // fall-through since they're just hidden
00129                 default:
00130                     previousCellPosition = CartesianDiagramDataCompressor::CachePosition();
00131                     continue;
00132                 }
00133             }
00134 
00135             const CartesianDiagramDataCompressor::DataPoint lastPoint = compressor().data( previousCellPosition );
00136             // area corners, a + b are the line ends:
00137             const QPointF a( plane->translate( QPointF( lastPoint.key, lastPoint.value ) ) );
00138             const QPointF b( plane->translate( QPointF( point.key, point.value ) ) );
00139             const QPointF c( plane->translate( QPointF( lastPoint.key, 0.0 ) ) );
00140             const QPointF d( plane->translate( QPointF( point.key, 0.0 ) ) );
00141 
00142             // add data point labels:
00143             const PositionPoints pts = PositionPoints( b, a, d, c );
00144             // if necessary, add the area to the area list:
00145             QList<QPolygonF> areas;
00146             if ( laCell.displayArea() ) {
00147                 QPolygonF polygon;
00148                 polygon << a << b << d << c;
00149                 areas << polygon;
00150             }
00151             // add the pieces to painting if this is not hidden:
00152             if ( !point.hidden /*&& !ISNAN( lastPoint.key ) && !ISNAN( lastPoint.value ) */) {
00153                 appendDataValueTextInfoToList( diagram(), textInfoList, sourceIndex, pts,
00154                                                Position::NorthWest, Position::SouthWest,
00155                                                point.value );
00156                 if( !ISNAN( lastPoint.key ) && !ISNAN( lastPoint.value ) )
00157                 {
00158                     paintAreas( ctx, attributesModel()->mapToSource( lastPoint.index ), areas, laCell.transparency() );
00159                     lineList.append( LineAttributesInfo( sourceIndex, a, b ) );
00160                 }
00161             }
00162 
00163             // wrap it up:
00164             previousCellPosition = position;
00165             laPreviousCell = laCell;
00166         }
00167         LineAttributes::MissingValuesPolicy policy = LineAttributes::MissingValuesAreBridged; //unused
00168         paintElements( ctx, textInfoList, lineList, policy );
00169     }
00170 }

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