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