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 "KDChartPlotter.h"
00031
00032 #include "KDChartPlotter_p.h"
00033
00034 #include "KDChartValueTrackerAttributes.h"
00035
00036 using namespace KDChart;
00037
00038 Plotter::Private::Private( const Private& rhs )
00039 : AbstractCartesianDiagram::Private( rhs )
00040 {
00041 }
00042
00043 void Plotter::Private::paintPolyline(
00044 PaintContext* ctx,
00045 const QBrush& brush, const QPen& pen,
00046 const QPolygonF& points ) const
00047 {
00048 ctx->painter()->setBrush( brush );
00049 ctx->painter()->setPen(
00050 QPen( pen.color(),
00051 pen.width(),
00052 pen.style(),
00053 Qt::FlatCap,
00054 Qt::MiterJoin ) );
00055 #if QT_VERSION > 0x040299
00056 ctx->painter()->drawPolyline( points );
00057 #else
00058
00059
00060
00061 for (int i = 0; i < points.size()-1; ++i)
00062 ctx->painter()->drawLine( points.at(i), points.at(i+1) );
00063 #endif
00064 }
00065
00071 const QPointF Plotter::PlotterType::project(
00072 QPointF point, QPointF maxLimits,
00073 double z, const QModelIndex& index ) const
00074 {
00075 Q_UNUSED( maxLimits );
00076 ThreeDLineAttributes td = diagram()->threeDLineAttributes( index );
00077
00078
00079 double xrad = DEGTORAD( td.lineXRotation() );
00080 double yrad = DEGTORAD( td.lineYRotation() );
00081 QPointF ret = QPointF(point.x()*cos( yrad ) + z * sin( yrad ) , point.y()*cos( xrad ) - z * sin( xrad ) );
00082 return ret;
00083 }
00084
00085 void Plotter::PlotterType::paintThreeDLines(
00086 PaintContext* ctx, const QModelIndex& index,
00087 const QPointF& from, const QPointF& to, const double depth )
00088 {
00089
00090 const QPair< QPointF, QPointF > boundaries = diagram()->dataBoundaries();
00091 const QPointF& maxLimits = boundaries.second;
00092 const QPointF topLeft = project( from, maxLimits, depth, index );
00093 const QPointF topRight = project ( to, maxLimits, depth, index );
00094
00095 const QPolygonF segment = QPolygonF() << from << topLeft << topRight << to;
00096 const QBrush indexBrush ( diagram()->brush( index ) );
00097 const PainterSaver painterSaver( ctx->painter() );
00098
00099 if( diagram()->antiAliasing() )
00100 ctx->painter()->setRenderHint( QPainter::Antialiasing );
00101
00102 ctx->painter()->setBrush( indexBrush );
00103 ctx->painter()->setPen( diagram()->pen( index ) ) ;
00104
00105 reverseMapper().addPolygon( index.row(), index.column(), segment );
00106 ctx->painter()->drawPolygon( segment );
00107 }
00108
00109
00110
00111
00112 void Plotter::PlotterType::paintElements(
00113 PaintContext* ctx,
00114 DataValueTextInfoList& list,
00115 LineAttributesInfoList& lineList,
00116 LineAttributes::MissingValuesPolicy policy )
00117 {
00118 Q_UNUSED( policy );
00119
00120 PainterSaver painterSaver( ctx->painter() );
00121 if ( diagram()->antiAliasing() )
00122 ctx->painter()->setRenderHint ( QPainter::Antialiasing );
00123 LineAttributesInfoListIterator itline ( lineList );
00124
00125 QBrush curBrush;
00126 QPen curPen;
00127 QPolygonF points;
00128 while ( itline.hasNext() ) {
00129 const LineAttributesInfo& lineInfo = itline.next();
00130 const QModelIndex& index = lineInfo.index;
00131 const ThreeDLineAttributes td = diagram()->threeDLineAttributes( index );
00132 const ValueTrackerAttributes vt = diagram()->valueTrackerAttributes( index );
00133
00134 if( td.isEnabled() ){
00135 paintThreeDLines( ctx, index, lineInfo.value, lineInfo.nextValue, td.depth() );
00136 } else {
00137 const QBrush br( diagram()->brush( index ) );
00138 const QPen pn( diagram()->pen( index ) );
00139 if( points.count() && points.last() == lineInfo.value && curBrush == br && curPen == pn ) {
00140
00141 reverseMapper().addLine( lineInfo.index.row(), lineInfo.index.column(), points.last(), lineInfo.nextValue );
00142 points << lineInfo.nextValue;
00143 } else {
00144 if( points.count() )
00145 paintPolyline( ctx, curBrush, curPen, points );
00146 curBrush = br;
00147 curPen = pn;
00148 points.clear();
00149
00150 reverseMapper().addLine( lineInfo.index.row(), lineInfo.index.column(), lineInfo.value, lineInfo.nextValue );
00151 points << lineInfo.value << lineInfo.nextValue;
00152 }
00153 }
00154
00155 if( vt.isEnabled() )
00156 paintValueTracker( ctx, vt, lineInfo.value );
00157 }
00158 if( points.count() )
00159 paintPolyline( ctx, curBrush, curPen, points );
00160
00161 paintDataValueTextsAndMarkers( diagram(), ctx, list, true );
00162 }
00163
00164 AttributesModel* Plotter::PlotterType::attributesModel() const
00165 {
00166 return m_private->attributesModel;
00167 }
00168
00169 #if 0
00170 QModelIndex LineDiagram::LineDiagramType::attributesModelRootIndex() const
00171 {
00172 return m_private->diagram->attributesModelRootIndex();
00173 }
00174
00175 int LineDiagram::LineDiagramType::datasetDimension() const
00176 {
00177 return m_private->datasetDimension;
00178 }
00179 #endif
00180
00181 ReverseMapper& Plotter::PlotterType::reverseMapper()
00182 {
00183 return m_private->reverseMapper;
00184 }
00185
00186 #if 0
00187 LineAttributes::MissingValuesPolicy LineDiagram::LineDiagramType::getCellValues(
00188 int row, int column,
00189 bool shiftCountedXValuesByHalfSection,
00190 double& valueX, double& valueY ) const
00191 {
00192 return m_private->diagram->getCellValues( row, column, shiftCountedXValuesByHalfSection,
00193 valueX, valueY );
00194 }
00195
00196 double LineDiagram::LineDiagramType::valueForCellTesting(
00197 int row, int column,
00198 bool& bOK,
00199 bool showHiddenCellsAsInvalid) const
00200 {
00201 return m_private->diagram->valueForCellTesting( row, column, bOK, showHiddenCellsAsInvalid );
00202 }
00203 #endif
00204
00205 Plotter* Plotter::PlotterType::diagram() const
00206 {
00207 return m_private->diagram;
00208 }
00209
00210 void Plotter::PlotterType::paintAreas(
00211 PaintContext* ctx,
00212 const QModelIndex& index, const QList< QPolygonF >& areas,
00213 const uint transparency )
00214 {
00215 QColor trans = diagram()->brush( index ).color();
00216 trans.setAlpha( transparency );
00217 QPen indexPen = diagram()->pen(index);
00218 indexPen.setColor( trans );
00219 const PainterSaver painterSaver( ctx->painter() );
00220
00221 if( diagram()->antiAliasing() )
00222 ctx->painter()->setRenderHint( QPainter::Antialiasing );
00223
00224 ctx->painter()->setPen( indexPen );
00225 ctx->painter()->setBrush( trans );
00226
00227 QPainterPath path;
00228 for( int i = 0; i < areas.count(); ++i )
00229 {
00230 const QPolygonF& p = areas[ i ];
00231 path.addPolygon( p );
00232 reverseMapper().addPolygon( index.row(), index.column(), p );
00233 path.closeSubpath();
00234 }
00235 ctx->painter()->drawPath( path );
00236 }
00237
00238 #if 0
00239 double LineDiagram::LineDiagramType::valueForCell( int row, int column )
00240 {
00241 return diagram()->valueForCell( row, column );
00242 }
00243 #endif
00244
00245 void Plotter::PlotterType::appendDataValueTextInfoToList(
00246 AbstractDiagram * diagram,
00247 DataValueTextInfoList & list,
00248 const QModelIndex & index,
00249 const PositionPoints& points,
00250 const Position& autoPositionPositive,
00251 const Position& autoPositionNegative,
00252 const qreal value )
00253 {
00254 Q_UNUSED( autoPositionNegative );
00255 m_private->appendDataValueTextInfoToList( diagram, list, index, points,
00256 autoPositionPositive, autoPositionPositive, value );
00257 }
00258
00259 void Plotter::PlotterType::paintValueTracker( PaintContext* ctx, const ValueTrackerAttributes& vt, const QPointF& at )
00260 {
00261 CartesianCoordinatePlane* plane = qobject_cast<CartesianCoordinatePlane*>( ctx->coordinatePlane() );
00262 if( !plane )
00263 return;
00264
00265 DataDimensionsList gridDimensions = ctx->coordinatePlane()->gridDimensionsList();
00266 const QPointF bottomLeft( ctx->coordinatePlane()->translate(
00267 QPointF( plane->isHorizontalRangeReversed() ?
00268 gridDimensions.at( 0 ).end :
00269 gridDimensions.at( 0 ).start,
00270 plane->isVerticalRangeReversed() ?
00271 gridDimensions.at( 1 ).end :
00272 gridDimensions.at( 1 ).start ) ) );
00273 const QPointF markerPoint = at;
00274 const QPointF ordinatePoint( bottomLeft.x(), at.y() );
00275 const QPointF abscissaPoint( at.x(), bottomLeft.y() );
00276
00277 const QSizeF markerSize = vt.markerSize();
00278 const QRectF ellipseMarker = QRectF( at.x() - markerSize.width() / 2,
00279 at.y() - markerSize.height() / 2,
00280 markerSize.width(), markerSize.height() );
00281
00282 const QPointF ordinateMarker[3] = {
00283 QPointF( ordinatePoint.x(), at.y() + markerSize.height() / 2 ),
00284 QPointF( ordinatePoint.x() + markerSize.width() / 2, at.y() ),
00285 QPointF( ordinatePoint.x(), at.y() - markerSize.height() / 2 )
00286 };
00287
00288 const QPointF abscissaMarker[3] = {
00289 QPointF( at.x() + markerSize.width() / 2, abscissaPoint.y() ),
00290 QPointF( at.x(), abscissaPoint.y() - markerSize.height() / 2 ),
00291 QPointF( at.x() - markerSize.width() / 2, abscissaPoint.y() )
00292 };
00293
00294 QPointF topLeft = ordinatePoint;
00295 QPointF bottomRightOffset = abscissaPoint - topLeft;
00296 QSizeF size( bottomRightOffset.x(), bottomRightOffset.y() );
00297 QRectF area( topLeft, size );
00298
00299 PainterSaver painterSaver( ctx->painter() );
00300 ctx->painter()->setPen( vt.pen() );
00301 ctx->painter()->setBrush( QBrush() );
00302
00303 ctx->painter()->drawLine( markerPoint, ordinatePoint );
00304 ctx->painter()->drawLine( markerPoint, abscissaPoint );
00305
00306 ctx->painter()->fillRect( area, vt.areaBrush() );
00307
00308 ctx->painter()->drawEllipse( ellipseMarker );
00309
00310 ctx->painter()->setBrush( vt.pen().color() );
00311 ctx->painter()->drawPolygon( ordinateMarker, 3 );
00312 ctx->painter()->drawPolygon( abscissaMarker, 3 );
00313 }
00314
00315 CartesianDiagramDataCompressor& Plotter::PlotterType::compressor() const
00316 {
00317 return m_private->compressor;
00318 }