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