void RS_Painter::createEllipse(QPointArray& pa, const RS_Vector& cp, double radius1, double radius2, double angle, double angle1, double angle2, bool reversed) { double aStep; // Angle Step (rad) double a; // Current Angle (rad) aStep=0.01; RS_Vector vp; RS_Vector vc(cp.x, cp.y); vp.set(cp.x+cos(angle1)*radius1, cp.y-sin(angle1)*radius2); vp.rotate(vc, -angle); int i=0; pa.resize(i+1); pa.setPoint(i++, toScreenX(vp.x),toScreenY(vp.y)); if(!reversed) { // Arc Counterclockwise: if(angle1>angle2-RS_TOLERANCE) { angle2+=2*M_PI; } for(a=angle1+aStep; a<=angle2; a+=aStep) { vp.set(cp.x+cos(a)*radius1, cp.y-sin(a)*radius2); vp.rotate(vc, -angle); pa.resize(i+1); pa.setPoint(i++, toScreenX(vp.x),toScreenY(vp.y)); } } else { // Arc Clockwise: if(angle1<angle2+RS_TOLERANCE) { angle2-=2*M_PI; } for(a=angle1-aStep; a>=angle2; a-=aStep) { vp.set(cp.x+cos(a)*radius1, cp.y-sin(a)*radius2); vp.rotate(vc, -angle); pa.resize(i+1); pa.setPoint(i++, toScreenX(vp.x),toScreenY(vp.y)); } } vp.set(cp.x+cos(angle2)*radius1, cp.y-sin(angle2)*radius2); vp.rotate(vc, -angle); pa.resize(i+1); pa.setPoint(i++, toScreenX(vp.x),toScreenY(vp.y)); }
/*! \brief Draw dots \param painter Painter \param xMap x map \param yMap y map \param from index of the first point to be painted \param to index of the last point to be painted \sa QwtCurve::drawPolyline, QwtCurve::drawLine, QwtCurve::drawLines, QwtCurve::drawSpline, QwtCurve::drawSteps QwtCurve::drawPolyline, QwtCurve::drawPolygon */ void QwtCurve::drawDots(QPainter *painter, const QwtDiMap &xMap, const QwtDiMap &yMap, int from, int to) { const bool doFill = painter->brush().style() != Qt::NoBrush; QPointArray polyline; if ( doFill ) polyline.resize(to - from + 1); for (int i = from; i <= to; i++) { int xi = xMap.transform(x(i)); int yi = yMap.transform(y(i)); QwtPainter::drawPoint(painter, xi, yi); if ( doFill ) polyline.setPoint(i - from, xi, yi); } if ( doFill ) { closePolyline(xMap, yMap, polyline); painter->setPen(QPen(Qt::NoPen)); QwtPainter::drawPolygon(painter, polyline); } }
void KviCanvasView::dragPolygon(KviCanvasPolygon * it,const QPoint &p) { switch(m_dragMode) { case All: it->move(p.x() - m_dragBegin.x(),p.y() - m_dragBegin.y()); break; case SinglePoint: { QPointArray pnt = it->internalPoints(); pnt.setPoint(m_dragPointIndex,(int)((p.x() - it->x()) / it->scaleFactor()),(int)((p.y() - it->y()) / it->scaleFactor())); it->setInternalPoints(pnt); } break; case Scale: { double dDistance = ssm_hypot(p.x() - it->x(),p.y() - it->y()); double dOriginal = ssm_hypot(m_dragBegin.x(),m_dragBegin.y()); if(dOriginal < 1)dOriginal = 1; if(dDistance < 0.1)dDistance = 0.1; it->setScaleFactor(m_dragScaleFactor * dDistance / dOriginal); } break; case Rotate: { QPoint act((int)(p.x() - it->x()),(int)(p.y() - it->y())); double dAngle = ssm_2d_rotationAngle(m_dragBegin.x(),m_dragBegin.y(),act.x(),act.y()); // qDebug("%d,%d %d,%d %f",m_dragBegin.x(),m_dragBegin.y(),act.x(),act.y(),dAngle); QPointArray thePoints = m_dragPointArray.copy(); for(unsigned int i=0;i<thePoints.size();i++) { QPoint tmp = thePoints.point(i); double dx = tmp.x(); double dy = tmp.y(); ssm_2d_rotate(dx,dy,dAngle); thePoints.setPoint(i,(int)dx,(int)dy); } it->setInternalPoints(thePoints); } break; default: break; } canvas()->update(); }
QPointArray KoChild::oldPointArray( const QWMatrix &matrix ) { QPointArray arr = d->m_old; for( int i = 0; i < 4; ++i ) arr.setPoint( i, matrix.map( arr.point( i ) ) ); return arr; }
QPointArray QWMatrix::map( const QPointArray &a ) const { QPointArray result = a.copy(); int x, y; for ( int i=0; i<(int)result.size(); i++ ) { result.point( i, &x, &y ); map( x, y, &x, &y ); result.setPoint( i, x, y ); } return result; }
static void calcPolygonPoints(QPointArray &pnts,unsigned int nVertices) { double dDelta = (2 * M_PI) / nVertices; for(unsigned int i=0;i<nVertices;i++) { double dAng = dDelta * i; double theX = 300 * sin(dAng); double theY = 300 * cos(dAng); pnts.setPoint(i,(int)theX,(int)theY); } }
void TimelineSubItem::showItem( bool show, int coordY ) { KDGanttViewTaskItem::showItem( show, coordY ); int y; if ( coordY != 0 ) { y = coordY; } else { y = getCoordY(); } int startX = myGanttView->timeHeaderWidget()->getCoordX( myStartTime ); int endX = myGanttView->timeHeaderWidget()->getCoordX( myEndTime ); const int mw = qMax( 1, qMin( 4, endX - startX ) ); if ( !mLeft || mw != mMarkerWidth ) { if ( !mLeft ) { mLeft = new KDCanvasPolygon( myGanttView->timeTableWidget(), this, Type_is_KDGanttViewItem ); mLeft->setBrush( Qt::black ); } QPointArray a = QPointArray( 4 ); a.setPoint( 0, 0, -mw -myItemSize / 2 - 2 ); a.setPoint( 1, mw, -myItemSize / 2 - 2 ); a.setPoint( 2, mw, myItemSize / 2 + 2 ); a.setPoint( 3, 0, myItemSize / 2 + mw + 2 ); mLeft->setPoints( a ); } if ( !mRight || mw != mMarkerWidth ) { if ( !mRight ) { mRight = new KDCanvasPolygon( myGanttView->timeTableWidget(), this, Type_is_KDGanttViewItem ); mRight->setBrush( Qt::black ); } QPointArray a = QPointArray( 4 ); a.setPoint( 0, -mw, -myItemSize / 2 - 2 ); a.setPoint( 1, 0, -myItemSize / 2 - mw - 2 ); a.setPoint( 2, 0, myItemSize / 2 + mw + 2 ); a.setPoint( 3, -mw, myItemSize / 2 + 2 ); mRight->setPoints( a ); } mMarkerWidth = mw; mLeft->setX( startX ); mLeft->setY( y ); mLeft->setZ( startShape->z() - 1 ); mLeft->show(); mRight->setX( endX ); mRight->setY( y ); mRight->setZ( startShape->z() - 1 ); mRight->show(); }
void QwtCurve::closePolyline(const QwtDiMap &xMap, const QwtDiMap &yMap, QPointArray &pa) const { const int sz = pa.size(); if ( sz < 2 ) return; pa.resize(sz + 2); if ( d_options & QwtCurve::Xfy ) { pa.setPoint(sz, xMap.transform(d_ref), pa.point(sz - 1).y()); pa.setPoint(sz + 1, xMap.transform(d_ref), pa.point(0).y()); } else { pa.setPoint(sz, pa.point(sz - 1).x(), yMap.transform(d_ref)); pa.setPoint(pa.size() - 1, pa.point(0).x(), yMap.transform(d_ref)); } }
void MarkerBar::DrawMap() { QPixmap *pix=new QPixmap(size()); QPainter *p=new QPainter(pix); QPointArray *pt; p->fillRect(0,0,size().width(),size().height(),backgroundColor()); if(marker_length>0) { p->setPen(EVENT_EDITOR_START_MARKER); p->setBrush(EVENT_EDITOR_START_MARKER); p->fillRect(size().width()*marker_pos[MarkerBar::Start]/marker_length-2,0, 4,size().height(),EVENT_EDITOR_START_MARKER); pt=new QPointArray(3); pt->setPoint(0,size().width()*marker_pos[MarkerBar::Start]/marker_length-2, size().height()/2-1); pt->setPoint(1,size().width()*marker_pos[MarkerBar::Start]/marker_length-12, size().height()-2); pt->setPoint(2,size().width()*marker_pos[MarkerBar::Start]/marker_length-12, 1); p->drawPolygon(*pt); p->fillRect(size().width()*marker_pos[MarkerBar::End]/marker_length-2,0, 4,size().height(),EVENT_EDITOR_START_MARKER); pt->setPoint(0,size().width()*marker_pos[MarkerBar::End]/marker_length+2, size().height()/2-1); pt->setPoint(1,size().width()*marker_pos[MarkerBar::End]/marker_length+12, size().height()-2); pt->setPoint(2,size().width()*marker_pos[MarkerBar::End]/marker_length+12, 1); p->drawPolygon(*pt); delete pt; p->setPen(EVENT_EDITOR_PLAY_MARKER); p->setBrush(EVENT_EDITOR_PLAY_MARKER); p->fillRect(size().width()*marker_pos[MarkerBar::Play]/marker_length-1,0, 2,size().height(),EVENT_EDITOR_PLAY_MARKER); } p->end(); setPixmap(*pix); delete p; delete pix; }
void KDGanttViewTaskLink::initTaskLink() { horLineList = new QPtrList<KDCanvasLine>; verLineList = new QPtrList<KDCanvasLine>; horLineList2 = new QPtrList<KDCanvasLine>; verLineList2 = new QPtrList<KDCanvasLine>; horLineList3 = new QPtrList<KDCanvasLine>; topList = new QPtrList<KDCanvasPolygon>; topLeftList = new QPtrList<KDCanvasPolygon>; topRightList = new QPtrList<KDCanvasPolygon>; horLineList->setAutoDelete( true ); verLineList->setAutoDelete( true ); horLineList2->setAutoDelete( true ); verLineList2->setAutoDelete( true ); horLineList3->setAutoDelete( true ); topList->setAutoDelete( true ); topLeftList->setAutoDelete( true ); topRightList->setAutoDelete( true ); myTimeTable = fromList.getFirst()->myGanttView->myTimeTable; KDCanvasLine* horLine,*verLine; KDCanvasLine* horLine2,*verLine2; KDCanvasLine* horLine3; KDCanvasPolygon* top; KDCanvasPolygon* topLeft; KDCanvasPolygon* topRight; unsigned int i, j; for ( i = 0;i < fromList.count();++i) { for ( j = 0;j < toList.count();++j) { horLine = new KDCanvasLine(myTimeTable,this,Type_is_KDGanttTaskLink); verLine = new KDCanvasLine(myTimeTable,this,Type_is_KDGanttTaskLink); horLine2 = new KDCanvasLine(myTimeTable,this,Type_is_KDGanttTaskLink); verLine2 = new KDCanvasLine(myTimeTable,this,Type_is_KDGanttTaskLink); horLine3 = new KDCanvasLine(myTimeTable,this,Type_is_KDGanttTaskLink); top = new KDCanvasPolygon(myTimeTable,this,Type_is_KDGanttTaskLink); topLeft = new KDCanvasPolygon(myTimeTable,this,Type_is_KDGanttTaskLink); topRight = new KDCanvasPolygon(myTimeTable,this,Type_is_KDGanttTaskLink); QPointArray arr = QPointArray(3); arr.setPoint(0,-4,-5); arr.setPoint(1,4,-5); arr.setPoint(2,0,0); top->setPoints(arr); arr.setPoint(0,5,-5); // need an extra y pixel, canvas bug? arr.setPoint(1,5,5); // need an extra y pixel, canvas bug? arr.setPoint(2,0,0); topLeft->setPoints(arr); arr.setPoint(0,-5,-4); arr.setPoint(1,-5,4); arr.setPoint(2,0,0); topRight->setPoints(arr); horLineList->append(horLine); verLineList->append(verLine); horLineList2->append(horLine2); verLineList2->append(verLine2); horLineList3->append(horLine3); topList->append(top); topLeftList->append(topLeft); topRightList->append(topRight); horLine->setZ(1); verLine->setZ(1); horLine2->setZ(1); verLine2->setZ(1); horLine3->setZ(1); top->setZ(1); topLeft->setZ(1); topRight->setZ(1); } } setTooltipText( "Tasklink" ); setWhatsThisText( "Tasklink" ); myTimeTable->myTaskLinkList.append(this); setHighlight( false); setHighlightColor(Qt::red ); setColor(Qt::black); setVisible(true); }
// motif arrows look the same whether they are used or not // is this correct? static void qDrawMotifArrow( QPainter *p, Qt::ArrowType type, bool down, int x, int y, int w, int h, const QColorGroup &g, bool ) { QPointArray bFill; // fill polygon QPointArray bTop; // top shadow. QPointArray bBot; // bottom shadow. QPointArray bLeft; // left shadow. #ifndef QT_NO_TRANSFORMATIONS QWMatrix matrix; // xform matrix #endif bool vertical = type == Qt::UpArrow || type == Qt::DownArrow; bool horizontal = !vertical; int dim = w < h ? w : h; int colspec = 0x0000; // color specification array if ( dim < 2 ) // too small arrow return; if ( dim > 3 ) { if ( dim > 6 ) bFill.resize( dim & 1 ? 3 : 4 ); bTop.resize( (dim/2)*2 ); bBot.resize( dim & 1 ? dim + 1 : dim ); bLeft.resize( dim > 4 ? 4 : 2 ); bLeft.putPoints( 0, 2, 0,0, 0,dim-1 ); if ( dim > 4 ) bLeft.putPoints( 2, 2, 1,2, 1,dim-3 ); bTop.putPoints( 0, 4, 1,0, 1,1, 2,1, 3,1 ); bBot.putPoints( 0, 4, 1,dim-1, 1,dim-2, 2,dim-2, 3,dim-2 ); for( int i=0; i<dim/2-2 ; i++ ) { bTop.putPoints( i*2+4, 2, 2+i*2,2+i, 5+i*2, 2+i ); bBot.putPoints( i*2+4, 2, 2+i*2,dim-3-i, 5+i*2,dim-3-i ); } if ( dim & 1 ) // odd number size: extra line bBot.putPoints( dim-1, 2, dim-3,dim/2, dim-1,dim/2 ); if ( dim > 6 ) { // dim>6: must fill interior bFill.putPoints( 0, 2, 1,dim-3, 1,2 ); if ( dim & 1 ) // if size is an odd number bFill.setPoint( 2, dim - 3, dim / 2 ); else bFill.putPoints( 2, 2, dim-4,dim/2-1, dim-4,dim/2 ); } } else { if ( dim == 3 ) { // 3x3 arrow pattern bLeft.setPoints( 4, 0,0, 0,2, 1,1, 1,1 ); bTop .setPoints( 2, 1,0, 1,0 ); bBot .setPoints( 2, 1,2, 2,1 ); } else { // 2x2 arrow pattern bLeft.setPoints( 2, 0,0, 0,1 ); bTop .setPoints( 2, 1,0, 1,0 ); bBot .setPoints( 2, 1,1, 1,1 ); } } if ( type == Qt::UpArrow || type == Qt::LeftArrow ) { #ifndef QT_NO_TRANSFORMATIONS // #### fix me! matrix.translate( x, y ); if ( vertical ) { matrix.translate( 0, h - 1 ); matrix.rotate( -90 ); } else { matrix.translate( w - 1, h - 1 ); matrix.rotate( 180 ); } #endif if ( down ) colspec = horizontal ? 0x2334 : 0x2343; else colspec = horizontal ? 0x1443 : 0x1434; } else if ( type == Qt::DownArrow || type == Qt::RightArrow ) { #ifndef QT_NO_TRANSFORMATIONS // #### fix me! matrix.translate( x, y ); if ( vertical ) { matrix.translate( w-1, 0 ); matrix.rotate( 90 ); } #endif if ( down ) colspec = horizontal ? 0x2443 : 0x2434; else colspec = horizontal ? 0x1334 : 0x1343; } QColor *cols[5]; cols[0] = 0; cols[1] = (QColor *)&g.button(); cols[2] = (QColor *)&g.mid(); cols[3] = (QColor *)&g.light(); cols[4] = (QColor *)&g.dark(); #define CMID *cols[ (colspec>>12) & 0xf ] #define CLEFT *cols[ (colspec>>8) & 0xf ] #define CTOP *cols[ (colspec>>4) & 0xf ] #define CBOT *cols[ colspec & 0xf ] QPen savePen = p->pen(); // save current pen QBrush saveBrush = p->brush(); // save current brush #ifndef QT_NO_TRANSFORMATIONS QWMatrix wxm = p->worldMatrix(); #endif QPen pen( Qt::NoPen ); const QBrush &brush = g.brush( QColorGroup::Button ); p->setPen( pen ); p->setBrush( brush ); #ifndef QT_NO_TRANSFORMATIONS p->setWorldMatrix( matrix, TRUE ); // set transformation matrix #endif p->drawPolygon( bFill ); // fill arrow p->setBrush( Qt::NoBrush ); // don't fill p->setPen( CLEFT ); p->drawLineSegments( bLeft ); p->setPen( CTOP ); p->drawLineSegments( bTop ); p->setPen( CBOT ); p->drawLineSegments( bBot ); #ifndef QT_NO_TRANSFORMATIONS p->setWorldMatrix( wxm ); #endif p->setBrush( saveBrush ); // restore brush p->setPen( savePen ); // restore pen #undef CMID #undef CLEFT #undef CTOP #undef CBOT }
void KDChartLinesPainter::specificPaintData( QPainter* painter, const QRect& /*ourClipRect*/, KDChartTableDataBase* data, KDChartDataRegionList* regions, const KDChartAxisParams* ordinatePara, bool /*bNormalMode*/, uint chart, double logWidth, double /*areaWidthP1000*/, double logHeight, double axisYOffset, double minColumnValue, double maxColumnValue, double columnValueDistance, uint /*chartDatasetStart*/, uint /*chartDatasetEnd*/, uint datasetStart, uint datasetEnd ) { if( !data ) return; abscissaInfos ai; ai.bCenterThePoints = mCenterThePoints; calculateAbscissaInfos( *params(), *data, datasetStart, datasetEnd, logWidth, _dataRect, ai ); mCenterThePoints = ai.bCenterThePoints; bool bOrdinateDecreasing = ordinatePara ? ordinatePara->axisValuesDecreasing() : false; bool bOrdinateIsLogarithmic = ordinatePara ? (KDChartAxisParams::AxisCalcLogarithmic == ordinatePara->axisCalcMode()) : false; //const double ordinatePixelsPerUnit = logHeight / columnValueDistance; const double ordinatePixelsPerUnit = ( ordinatePara && (0.0 != ordinatePara->trueAxisDeltaPixels()) && (0.0 != ordinatePara->trueAxisDelta())) ? ordinatePara->trueAxisDeltaPixels() / ordinatePara->trueAxisDelta() : logHeight / columnValueDistance;; //qDebug("ordinatePixelsPerUnit: %f",ordinatePixelsPerUnit); const bool showThreeDLines = !mIsArea && params()->threeDLines(); enum { Normal, Stacked, Percent } mode = Normal; if ( ( ( mChartType == KDChartParams::Line ) && ( params()->lineChartSubType() == KDChartParams::LineNormal ) ) || ( ( mChartType == KDChartParams::Area ) && ( params()->areaChartSubType() == KDChartParams::AreaNormal ) ) ) mode = Normal; else if ( ( ( mChartType == KDChartParams::Line ) && ( params()->lineChartSubType() == KDChartParams::LineStacked ) ) || ( ( mChartType == KDChartParams::Area ) && ( params()->areaChartSubType() == KDChartParams::AreaStacked ) ) ) mode = Stacked; else if ( ( ( mChartType == KDChartParams::Line ) && ( params()->lineChartSubType() == KDChartParams::LinePercent ) ) || ( ( mChartType == KDChartParams::Area ) && ( params()->areaChartSubType() == KDChartParams::AreaPercent ) ) ) mode = Percent; else qDebug( "Internal error in KDChartLinesPainter::paintDataInternal(): Unknown subtype" ); QMap < int, double > currentValueSums; if ( mode == Stacked || mode == Percent ) { // this array is only used for stacked and percent lines, no need // to waste time initializing it for normal types for ( int value = 0; value < ai.numValues; ++value ) currentValueSums[ value ] = 0.0; } QMap < int, double > totalValueSums; // compute the position of the 0 axis double zeroXAxisI; if ( mode == Percent ) { if ( minColumnValue == 0.0 ) zeroXAxisI = logHeight + axisYOffset; else if( maxColumnValue == 0.0 ) zeroXAxisI = _dataRect.y() + axisYOffset; else zeroXAxisI = logHeight / 2.0 + _dataRect.y(); } else zeroXAxisI = ordinatePara->axisZeroLineStartY() - _dataRect.y(); // compute how to shift of the points in case we want them in the // middle of their respective columns int xShift = mCenterThePoints ? static_cast < int > ( ai.pointDist * 0.5 ) : 0; // calculate all points' positions // =============================== int arrayNumDatasets = 0; int arrayNumValues = ai.bAbscissaHasTrueAxisDtValues ? data->cols() : ai.numValues; int dataset; for( dataset = datasetEnd; ( dataset >= static_cast < int > ( datasetStart ) && dataset >= 0 ); --dataset ) ++arrayNumDatasets; #if COMPAT_QT_VERSION >= 0x030000 QValueVector<MyPoint> allPoints( #else QArray<MyPoint> allPoints( #endif arrayNumDatasets * arrayNumValues ); KDChartPropertySet curPropSet; int curPropSetId = KDChartPropertySet::UndefinedID; for( dataset = datasetEnd; ( dataset >= (int)datasetStart && dataset >= 0 ); --dataset ) { int prevPointX = -1; int prevPointY = -1; const KDChartParams::LineMarkerStyle defaultMarkerStyle = params()->lineMarkerStyle( dataset ); const QPen default2DPen( params()->lineColor().isValid() ? params()->lineColor() : params()->dataColor( dataset ), params()->lineWidth(), params()->lineStyle( dataset ) ); if( ai.bAbscissaHasTrueAxisDtValues ) ai.numValues = data->cols(); QVariant vValY; QVariant vValX; int cellPropID; for( int value = 0; value < ai.numValues; ++value ) { //if ( mode == Percent ) // valueTotal = data->colAbsSum( value ); double valueTotal = 0.0; // Will only be used for Percent if( mode == Percent ) { valueTotal = 0.0; // iterate over datasets of this axis only: for ( uint dataset2 = datasetStart; dataset2 <= datasetEnd; ++dataset2 ) { if( data->cellCoord( dataset2, value, vValY, 1 ) && QVariant::Double == vValY.type() ) valueTotal += vValY.toDouble(); } } if( data->cellContent( dataset, value, vValY, vValX, cellPropID ) && QVariant::Double == vValY.type() && ( !ai.bCellsHaveSeveralCoordinates || QVariant::Invalid != vValX.type() ) ){ //qDebug("a. cellPropID: %i",cellPropID); // calculate Ordinate axis value // ----------------------------- double cellValue = vValY.toDouble(); double drawValue = 0.0; // PENDING(kalle) This does not work for AreaPercent yet if ( mode == Stacked ) drawValue = ( cellValue + currentValueSums[ value ] ) * ordinatePixelsPerUnit; else if ( mode == Percent ) drawValue = ( ( cellValue + currentValueSums[ value ] ) / valueTotal ) * 100.0 * ordinatePixelsPerUnit; else { // LineNormal or AreaNormal if( bOrdinateIsLogarithmic ){ if( 0.0 < cellValue ) drawValue = log10( cellValue ) * ordinatePixelsPerUnit; else drawValue = -10250.0; //qDebug("\nlogarithmic calc - cellValue: %f drawValue: %f", // cellValue, drawValue ); }else{ drawValue = cellValue * ordinatePixelsPerUnit * (bOrdinateDecreasing ? -1.0 : 1.0); //qDebug("\nlinear calc - cellValue: %f\n - drawValue: %f", // cellValue, drawValue ); } } // calculate Abscissa axis value // ----------------------------- double xValue; bool skipMe = !calculateAbscissaAxisValue( vValX, ai, value, xValue ); // calculate and store the point and region / draw the marker // ---------------------------------------------------------- if( !skipMe ){ // prevent the point from being toooo far // below the bottom (or above the top, resp.) // of the cliprect double pY = QMIN( zeroXAxisI - drawValue, (logHeight + axisYOffset) * 3 ); pY = QMAX( pY, -(logHeight + axisYOffset) * 3 ); // specify the Point int myPointX = static_cast < int > ( xValue ) + xShift; int myPointY = static_cast < int > ( pY ); if( cellPropID == curPropSetId && myPointX == prevPointX && myPointY == prevPointY ){ allPoints[ static_cast < int > ( datasetEnd-dataset ) * arrayNumValues + value ].setSkipThis( true ); skipMe = true; //qDebug("skipped"); }else{ // use typecast to make it compile on windows using qt232 allPoints[ static_cast < int > ( datasetEnd-dataset ) * arrayNumValues + value ].set( myPointX, myPointY, cellValue ); //qDebug("ok"); } if( !skipMe ){ // -------------------------------------------------------- // determine any 'extra' properties assigned to this cell // by traversing the property set chain (if necessary) // -------------------------------------------------------- if( cellPropID != curPropSetId ){ //qDebug("b. ( curPropSetId: %i )",curPropSetId); //qDebug("b. cellPropID: %i",cellPropID); //qDebug(curPropSet.name().latin1()); if( cellPropID != KDChartPropertySet::UndefinedID && params()->calculateProperties( cellPropID, curPropSet ) ){ curPropSetId = cellPropID; //qDebug("c. curPropSetId: %i",curPropSetId); //qDebug(curPropSet.name().latin1()); }else{ curPropSetId = KDChartPropertySet::UndefinedID; } } // make sure any extra horiz. and/or vert. lines and/or markers // are drawn *before* the data lines and/or markers are painted if( mChartType == KDChartParams::Line ){ if( curPropSetId != KDChartPropertySet::UndefinedID ){ drawExtraLinesAndMarkers( curPropSet, default2DPen, defaultMarkerStyle, myPointX, myPointY, painter, ai.abscissaPara, ordinatePara, logWidth/1000.0, logHeight/1000.0, false ); } } prevPointX = myPointX; prevPointY = myPointY; } } // calculate running sum for stacked and percent if ( mode == Stacked || mode == Percent ) { if( cellValue == KDCHART_POS_INFINITE ) currentValueSums[ value ] = KDCHART_POS_INFINITE; else if( currentValueSums[ value ] != KDCHART_POS_INFINITE ) currentValueSums[ value ] += cellValue; } } } } QPointArray previousPoints; // no vector since only areas need it, // and these do not support 3d yet // Store some (dataset-independend) default values // to be used unless other properties // have been specified for the respective data cell: // const bool defaultDrawMarkers = mDrawMarkers; for ( dataset = datasetEnd; ( dataset >= (int)datasetStart && dataset >= 0 ); --dataset ) { // Store some (dataset-dependend) default values // to be used unless other properties // have been specified for the respective data cell: // const QPen default2DPen( params()->lineColor().isValid() ? params()->lineColor() : params()->dataColor( dataset ), params()->lineWidth(), params()->lineStyle( dataset ) ); bool currentDrawMarkers = defaultDrawMarkers; const KDChartParams::LineMarkerStyle markerStyle = params()->lineMarkerStyle( dataset ); // the +2 is for the areas (if any) QPtrVector< QPointArray > points( 2 ); points.setAutoDelete( true ); /* Pending Michel - we need to keep track of the * non rotated points for 3D lines */ QPtrVector< QPointArray > oripoints( 2 ); oripoints.setAutoDelete( true ); int i = 0; for( i = 0; i < 2; ++i ) { points.insert( i, new QPointArray( ai.numValues + 2 ) ); oripoints.insert( i, new QPointArray( ai.numValues + 2 ) ); } if( ai.bAbscissaHasTrueAxisDtValues ) ai.numValues = data->cols(); int point = 0; for ( int value = 0; value < ai.numValues; ++value ) { // determine and store marker properties assigned to this cell // ----------------------------------------------------------- currentDrawMarkers = defaultDrawMarkers; int cellPropID; if( data->cellProp( dataset, value, cellPropID ) && cellPropID != curPropSetId ){ if( cellPropID != KDChartPropertySet::UndefinedID && params()->calculateProperties( cellPropID, curPropSet ) ) curPropSetId = cellPropID; else curPropSetId = KDChartPropertySet::UndefinedID; } if( curPropSetId != KDChartPropertySet::UndefinedID ){ // we can safely call the following functions and ignore their // return values since they will touch the parameters' values // if the propSet *contains* corresponding own values only. int iDummy; curPropSet.hasOwnShowMarker( iDummy, currentDrawMarkers ); } int iVec = static_cast < int > ( datasetEnd-dataset ) * arrayNumValues + value; if( allPoints[ iVec ].bValid && !allPoints[ iVec ].bSkipThis ){ const MyPoint& mp = allPoints[iVec]; //qDebug("\np.x() %i p.y() %i", p.x(), p.y() ); // For 3D lines, we need two points (that lie // behind each other on the Z axis). For 2D lines and // areas, we need only one point. if( showThreeDLines ) { points[0]->setPoint( point, project( mp.p.x(), mp.p.y(), (datasetStart+dataset)*params()->threeDLineDepth() ) ); points[1]->setPoint( point, project( mp.p.x(), mp.p.y(), (datasetStart+dataset + 1)*params()->threeDLineDepth() ) ); oripoints[0]->setPoint( point, mp.p.x(), mp.p.y() ); oripoints[1]->setPoint( point, mp.p.x() - (datasetStart+dataset + 1)*params()->threeDLineDepth(), mp.p.y() - (datasetStart+dataset + 1)*params()->threeDLineDepth() ); } else // 2D lines or areas points[0]->setPoint( point, mp.p ); ++point; int x = mp.p.x(); int y = QMAX(QMIN(mp.p.y(), static_cast < int > (logHeight +axisYOffset)), 0); bool markerIsOutside = y != mp.p.y(); // draw the marker and store the region if ( currentDrawMarkers ){ uint theAlignment = Qt::AlignCenter; bool hasOwnSize = false; int theWidth = 0; int theHeight = 0; QColor theColor(params()->dataColor( dataset )); int theStyle = markerStyle; if( curPropSetId != KDChartPropertySet::UndefinedID ){ // we can safely call the following functions and ignore their // return values since they will touch the parameters' values // if the propSet *contains* corresponding own values only. int iDummy; curPropSet.hasOwnMarkerAlign( iDummy, theAlignment ); curPropSet.hasOwnMarkerColor( iDummy, theColor ); curPropSet.hasOwnMarkerStyle( iDummy, theStyle ); QSize size(theWidth, theHeight); hasOwnSize = curPropSet.hasOwnMarkerSize(iDummy, size); if( hasOwnSize ){ theWidth = size.width(); theHeight = size.height(); } } drawMarker( painter, params(), _areaWidthP1000, _areaHeightP1000, _dataRect.x(), _dataRect.y(), markerIsOutside ? KDChartParams::LineMarker1Pixel : theStyle, theColor, QPoint(x,y), dataset, value, chart, regions, hasOwnSize ? &theWidth : 0, hasOwnSize ? &theHeight : 0, theAlignment ); } // store the region else if( regions ) { QRect rect( QPoint( x-params()->lineWidth()-1, y-params()->lineWidth()-1 ), QPoint( x+params()->lineWidth()+1, y+params()->lineWidth()+1 ) ); rect.moveBy( _dataRect.x(), _dataRect.y() ); regions->append( new KDChartDataRegion(dataset, value, chart, rect) ); } } } if ( point ) { bool bDrawLines = (0 != params()->lineWidth()); if ( mIsArea ) { // first draw with the fill brush, no pen, with the // zero axis points or upper border points added for the first // dataset or with the previous points reversed for all other // datasets. painter->setPen( QPen( Qt::NoPen ) ); const QBrush datasetBrush( params()->dataColor( dataset ), Qt::SolidPattern ); painter->setBrush( datasetBrush ); QBrush currentBrush( datasetBrush ); if ( mode == Normal || dataset == (int)datasetEnd ) { /// first dataset (or any dataset in normal mode, where /// the datasets overwrite each other) // no 3d handling for areas yet QPoint lastPoint = points[0]->point( point - 1 ); // zeroXAxisI can be too far below the abscissa, but it's // the only thing we have. Likewise can 0 be too far above // the upper boundary, but again it's the only thing we // have, at the rest is clipped anyway. int yCoord; if ( params()->areaLocation() == KDChartParams::AreaBelow || mode == Percent ) yCoord = static_cast<int>(zeroXAxisI); else yCoord = static_cast<int>(axisYOffset); // old: draw the complete area in on go: /* // no 3d handling for areas yet points[0]->setPoint( point, lastPoint.x(), yCoord ); point++; QPoint firstPoint = points[0]->point( 0 ); points[0]->setPoint( point, firstPoint.x(), yCoord ); point++; painter->drawPolygon( *points[0], false, 0, point ); */ // new: draw individual area segments: curPropSetId = KDChartPropertySet::UndefinedID; for( int value = 0; value < point-1; ++value ) { int cellPropID; if( data->cellProp( dataset, value, cellPropID ) && cellPropID != curPropSetId ){ if( cellPropID != KDChartPropertySet::UndefinedID && params()->calculateProperties( cellPropID, curPropSet ) ){ curPropSetId = cellPropID; }else{ curPropSetId = KDChartPropertySet::UndefinedID; } // preset with default value QBrush theAreaBrush = datasetBrush; if( curPropSetId != KDChartPropertySet::UndefinedID ){ // we can safely call the following functions and ignore their // return values since they will touch the parameters' values // if the propSet *contains* corresponding own values only. int iDummy; curPropSet.hasOwnAreaBrush( iDummy, theAreaBrush ); } painter->setBrush( theAreaBrush ); } QPointArray segment( 4 ); segment.setPoint( 0, points[0]->point( value ) ); segment.setPoint( 1, points[0]->point( value+1 ) ); segment.setPoint( 2, points[0]->point( value+1 ).x(), yCoord ); segment.setPoint( 3, points[0]->point( value ).x(), yCoord ); painter->drawPolygon( segment ); } // old: draw the complete area in on go: /* // remove the last two points added point -= 2; */ //qDebug("\n111"); } // if ( mode == Normal || dataset == (int)datasetEnd ) else { // don't mess around with the original array; we'll need // that for the next time through. //qDebug("222"); // no 3d handling for areas yet QPointArray thisSection = points[0]->copy(); thisSection.resize( point + previousPoints.size() ); // append the previous array (there is guaranteed to be // one because we are at least the second time through // here) in reverse order for ( unsigned int i = 0; i < previousPoints.size(); ++i ) { thisSection.setPoint( point + i, previousPoints.point( previousPoints.size() - i - 1 ) ); //qDebug("\nx: %i",previousPoints.point( previousPoints.size() - i - 1 ).x()); //qDebug("y: %i",previousPoints.point( previousPoints.size() - i - 1 ).y()); } painter->drawPolygon( thisSection ); } // draw the line with no brush and outline color painter->setBrush( Qt::NoBrush ); painter->setPen( QPen( params()->outlineDataColor(), params()->outlineDataLineWidth() ) ); } else { // line if( showThreeDLines ) { // This is a 3D line: // We draw the line with the data color brush // and the outline data pen. painter->setBrush( params()->dataColor( dataset ) ); painter->setPen( QPen( params()->outlineDataColor(), params()->outlineDataLineWidth() ) ); } else { // This is a 2D line: // We draw the line with the no brush // and the data color if no special line color was specified. painter->setBrush( Qt::NoBrush ); painter->setPen( default2DPen ); } } // Neither draw the contour line if this is a pure Point chart // nor draw it for the last row of a percent area chart. if( bDrawLines && ( (mode != Percent) || !mIsArea || (dataset != (int)datasetEnd) ) ){ if( showThreeDLines ) { // A 3D line needs to be drawn piece-wise for ( int value = 0; value < point-1; ++value ) { // if( data->cell( dataset, value ).hasValue() && // data->cell( dataset, value+1 ).hasValue() ) { // qDebug( "Draw a segment in dataset %d from %d to %d", dataset, value, value+1 ); //store the rotated points ( see project() ) QPointArray rotatedSegment( 4 ); rotatedSegment.setPoint( 0, points[0]->point( value )); rotatedSegment.setPoint( 1, points[0]->point( value+1 ) ); rotatedSegment.setPoint( 2, points[1]->point( value+1 ) ); rotatedSegment.setPoint( 3, points[1]->point( value ) ); //store the true points without rotation QPointArray trueSegment( 4 ); trueSegment.setPoint( 0, oripoints[0]->point( value )); trueSegment.setPoint( 1, oripoints[0]->point( value+1 ) ); trueSegment.setPoint( 2, oripoints[1]->point( value+1 ) ); trueSegment.setPoint( 3, oripoints[1]->point( value ) ); // calculate the rotated points position relative to each other // we will then be able to keep the rotation ( see: project () ) // by reporting this position relative to the true segment line //left side pt3 and pt0 int dx30 = rotatedSegment.point(3).x() - rotatedSegment.point(0).x(); int dy30 = rotatedSegment.point(3).y() - rotatedSegment.point(0).y(); //right side pt1 and pt2 int dx12 = rotatedSegment.point(2).x() - rotatedSegment.point(1).x(); int dy12 = rotatedSegment.point(2).y() - rotatedSegment.point(1).y(); // store and paint the "3D" segment QPointArray segment( 4 ); segment.setPoint( 0, trueSegment.point(0) ); segment.setPoint( 1, trueSegment.point(1) ); segment.setPoint( 2, trueSegment.point(1).x() + dx12, trueSegment.point(1).y() + dy12 ); segment.setPoint( 3, trueSegment.point(0).x() + dx30, trueSegment.point(0).y() + dy30); //PENDING Michel 3dlines drawing a segment with showThreeDLines painter->drawPolygon( segment ); // } else // qDebug( "Can't draw a segment in dataset %d from %d to %d", dataset, value, value+1 ); } } else { QPoint p1, p2; // Note: If markers are drawn very near to each other // and tiny markers are used // we don't draw the connecting lines. bool b4PMarkers = KDChartParams::LineMarker4Pixels == markerStyle; bool bTinyMarkers = KDChartParams::LineMarker1Pixel == markerStyle || b4PMarkers; curPropSetId = KDChartPropertySet::UndefinedID; painter->setPen( default2DPen ); for ( int value = 0; value < point-1; ++value ) { p1 = points[0]->point( value ); p2 = points[0]->point( value+1 ); // Determine properties assigned to this cell // and change the painter if necessarry: currentDrawMarkers = defaultDrawMarkers; int cellPropID; if( data->cellProp( dataset, value, cellPropID ) && cellPropID != curPropSetId ){ if( cellPropID != KDChartPropertySet::UndefinedID && params()->calculateProperties( cellPropID, curPropSet ) ){ curPropSetId = cellPropID; }else{ curPropSetId = KDChartPropertySet::UndefinedID; } // preset with default values int theLineWidth = default2DPen.width(); QColor theLineColor = default2DPen.color(); Qt::PenStyle theLineStyle = default2DPen.style(); if( curPropSetId != KDChartPropertySet::UndefinedID ){ // we can safely call the following functions and ignore their // return values since they will touch the parameters' values // if the propSet *contains* corresponding own values only. int iDummy; curPropSet.hasOwnLineWidth ( iDummy, theLineWidth ); curPropSet.hasOwnLineColor ( iDummy, theLineColor ); curPropSet.hasOwnLineStyle ( iDummy, theLineStyle ); curPropSet.hasOwnShowMarker( iDummy, currentDrawMarkers ); } painter->setPen( QPen( theLineColor, theLineWidth, theLineStyle ) ); } if( !currentDrawMarkers ){ //PENDING Michel: drawing a line - not currentMarkers painter->drawLine( p1, p2 ); }else{ int dx = p2.x() - p1.x(); int dy = p2.y() - p1.y(); if( !bTinyMarkers || (abs(dx) > 4) || (abs(dy) > 4) ){ if( bTinyMarkers ) { double m = !dx ? 100.0 : !dy ? 0.01 : ((double)dy / (double)dx); double am = fabs(m); int dxx; int dyy; if( 0.25 > am ){ dxx = 3; dyy = 0; }else if( 0.67 > am ){ dxx = 3; dyy = 1; }else if( 1.33 > am ){ dxx = 2; dyy = 2; }else if( 4.0 > am ){ dxx = 1; dyy = 3; }else{ dxx = 0; dyy = 3; } if( 0 > dx ) dxx *= -1; if( 0 > dy ) dyy *= -1; if( b4PMarkers ){ if( 0 < dx ) ++p1.rx(); else if( 0 > dx ) ++p2.rx(); if( 0 < dy ) ++p1.ry(); else if( 0 > dy ) ++p2.ry(); } p1.rx() += dxx; p1.ry() += dyy; p2.rx() -= dxx; p2.ry() -= dyy; } //PENDING Michel: drawing a line - currentMarkers painter->drawLine( p1, p2 ); } } } } } } // Save point array for next way through (needed for e.g. stacked // areas), not for 3D currently points[0]->resize( point ); previousPoints = points[0]->copy(); } // Now draw any extra lines (and/or their markers, resp.) that // are to be printed IN FRONT of the normal lines: if( mChartType == KDChartParams::Line ){ for( dataset = datasetEnd; ( dataset >= (int)datasetStart && dataset >= 0 ); --dataset ) { const KDChartParams::LineMarkerStyle defaultMarkerStyle = params()->lineMarkerStyle( dataset ); const QPen default2DPen( params()->lineColor().isValid() ? params()->lineColor() : params()->dataColor( dataset ), params()->lineWidth(), params()->lineStyle( dataset ) ); if( ai.bAbscissaHasTrueAxisDtValues ) ai.numValues = data->cols(); for ( int value = 0; value < ai.numValues; ++value ) { int iVec = static_cast < int > ( datasetEnd-dataset ) * arrayNumValues + value; if( allPoints[ iVec ].bValid ){ const MyPoint& mp = allPoints[iVec]; //qDebug("\np.x() %i p.y() %i", p.x(), p.y() ); // -------------------------------------------------------- // determine any 'extra' properties assigned to this cell // by traversing the property set chain (if necessary) // -------------------------------------------------------- int cellPropID; if( data->cellProp( dataset, value, cellPropID ) && cellPropID != curPropSetId ){ if( cellPropID != KDChartPropertySet::UndefinedID && params()->calculateProperties( cellPropID, curPropSet ) ) curPropSetId = cellPropID; else curPropSetId = KDChartPropertySet::UndefinedID; } if( curPropSetId != KDChartPropertySet::UndefinedID ){ drawExtraLinesAndMarkers( curPropSet, default2DPen, defaultMarkerStyle, mp.p.x(), mp.p.y(), painter, ai.abscissaPara, ordinatePara, logWidth/1000.0, logHeight/1000.0, true ); } } } } } //qDebug(const_cast < KDChartParams* > ( params() )->properties( KDCHART_PROPSET_NORMAL_DATA )->name().latin1()); //qDebug(const_cast < KDChartParams* > ( params() )->properties( KDCHART_PROPSET_TRANSPARENT_DATA )->name().latin1()); //qDebug(const_cast < KDChartParams* > ( params() )->properties( KDCHART_PROPSET_HORI_LINE )->name().latin1()); //qDebug(const_cast < KDChartParams* > ( params() )->properties( KDCHART_PROPSET_VERT_LINE )->name().latin1()); //qDebug("--"); }
static void addPoint( QPointArray &a, const QPoint &p ) { uint n = a.size(); a.resize( n + 1 ); a.setPoint( n, p ); }
void QCDEStyle::drawArrow( QPainter *p, ArrowType type, bool down, int x, int y, int w, int h, const QColorGroup &g, bool enabled, const QBrush * /* fill */ ) { QPointArray bFill; // fill polygon QPointArray bTop; // top shadow. QPointArray bBot; // bottom shadow. QPointArray bLeft; // left shadow. QWMatrix matrix; // xform matrix bool vertical = type == UpArrow || type == DownArrow; bool horizontal = !vertical; int dim = w < h ? w : h; int colspec = 0x0000; // color specification array if ( dim < 2 ) // too small arrow return; // adjust size and center (to fix rotation below) if ( w > dim ) { x += (w-dim)/2; w = dim; } if ( h > dim ) { y += (h-dim)/2; h = dim; } if ( dim > 3 ) { bFill.resize( dim & 1 ? 3 : 4 ); bTop.resize( 2 ); bBot.resize( 2 ); bLeft.resize( 2 ); bLeft.putPoints( 0, 2, 0,0, 0,dim-1 ); bTop.putPoints( 0, 2, 1,0, dim-1, dim/2); bBot.putPoints( 0, 2, 1,dim-1, dim-1, dim/2); if ( dim > 6 ) { // dim>6: must fill interior bFill.putPoints( 0, 2, 1,dim-1, 1,1 ); if ( dim & 1 ) // if size is an odd number bFill.setPoint( 2, dim - 2, dim / 2 ); else bFill.putPoints( 2, 2, dim-2,dim/2-1, dim-2,dim/2 ); } } else { if ( dim == 3 ) { // 3x3 arrow pattern bLeft.setPoints( 4, 0,0, 0,2, 1,1, 1,1 ); bTop .setPoints( 2, 1,0, 1,0 ); bBot .setPoints( 2, 1,2, 2,1 ); } else { // 2x2 arrow pattern bLeft.setPoints( 2, 0,0, 0,1 ); bTop .setPoints( 2, 1,0, 1,0 ); bBot .setPoints( 2, 1,1, 1,1 ); } } if ( type == UpArrow || type == LeftArrow ) { matrix.translate( x, y ); if ( vertical ) { matrix.translate( 0, h - 1 ); matrix.rotate( -90 ); } else { matrix.translate( w - 1, h - 1 ); matrix.rotate( 180 ); } if ( down ) colspec = horizontal ? 0x2334 : 0x2343; else colspec = horizontal ? 0x1443 : 0x1434; } else if ( type == DownArrow || type == RightArrow ) { matrix.translate( x, y ); if ( vertical ) { matrix.translate( w-1, 0 ); matrix.rotate( 90 ); } if ( down ) colspec = horizontal ? 0x2443 : 0x2434; else colspec = horizontal ? 0x1334 : 0x1343; } QColor *cols[5]; if ( enabled ) { cols[0] = 0; cols[1] = (QColor *)&g.button(); cols[2] = (QColor *)&g.mid(); cols[3] = (QColor *)&g.light(); cols[4] = (QColor *)&g.dark(); } else { cols[0] = 0; cols[1] = (QColor *)&g.button(); cols[2] = (QColor *)&g.button(); cols[3] = (QColor *)&g.button(); cols[4] = (QColor *)&g.button(); } #define CMID *cols[ (colspec>>12) & 0xf ] #define CLEFT *cols[ (colspec>>8) & 0xf ] #define CTOP *cols[ (colspec>>4) & 0xf ] #define CBOT *cols[ colspec & 0xf ] QPen savePen = p->pen(); // save current pen QBrush saveBrush = p->brush(); // save current brush QWMatrix wxm = p->worldMatrix(); QPen pen( NoPen ); QBrush brush = g.brush( enabled?QColorGroup::Button:QColorGroup::Mid ); p->setPen( pen ); p->setBrush( brush ); p->setWorldMatrix( matrix, TRUE ); // set transformation matrix p->drawPolygon( bFill ); // fill arrow p->setBrush( NoBrush ); // don't fill p->setPen( CLEFT ); p->drawLineSegments( bLeft ); p->setPen( CBOT ); p->drawLineSegments( bBot ); p->setPen( CTOP ); p->drawLineSegments( bTop ); p->setWorldMatrix( wxm ); p->setBrush( saveBrush ); // restore brush p->setPen( savePen ); // restore pen #undef CMID #undef CLEFT #undef CTOP #undef CBOT }
void toBarChart::paintChart ( QPainter *p, QRect &rect ) { QFontMetrics fm = p->fontMetrics(); if ( !Zooming ) { if ( MinAuto ) { bool first = true; std::list<std::list<double> >::reverse_iterator i = Values.rbegin(); if ( i != Values.rend() ) { for ( std::list<double>::iterator j = ( *i ).begin();j != ( *i ).end();j++ ) { if ( first ) { first = false; zMinValue = *j; } else if ( zMinValue > *j ) zMinValue = *j; } } } if ( MaxAuto ) { bool first = true; std::list<double> total; { for ( std::list<std::list<double> >::iterator i = Values.begin();i != Values.end();i++ ) { std::list<double>::iterator k = total.begin(); for ( std::list<double>::iterator j = ( *i ).begin();j != ( *i ).end();j++ ) { if ( k == total.end() ) { total.insert ( total.end(), *j ); k = total.end(); } else { *k += *j; k++; } } } } for ( std::list<double>::iterator i = total.begin();i != total.end();i++ ) { if ( first ) { first = false; zMaxValue = *i; } else if ( zMaxValue < *i ) zMaxValue = *i; } } if ( !MinAuto ) zMinValue = MinValue; else zMinValue = round ( zMinValue, false ); if ( !MaxAuto ) zMaxValue = MaxValue; else zMaxValue = round ( zMaxValue, true ); } paintTitle ( p, rect ); paintLegend ( p, rect ); paintAxis ( p, rect ); std::list<QPointArray> Points; int cp = 0; int samples = countSamples(); int zeroy = int ( rect.height() - 2 - ( -zMinValue / ( zMaxValue - zMinValue ) * ( rect.height() - 4 ) ) ); if ( samples > 1 ) { const QWMatrix & mtx = p->worldMatrix(); p->setClipRect ( int ( mtx.dx() + 2 ), int ( mtx.dy() + 2 ), rect.width() - 3, rect.height() - 3 ); if ( Zooming ) p->drawText ( 2, 2, rect.width() - 4, rect.height() - 4, AlignLeft | AlignTop, "Zoom" ); for ( std::list<std::list<double> >::reverse_iterator i = Values.rbegin();i != Values.rend();i++ ) { std::list<double> &val = *i; int count = 0; int skip = SkipSamples; QPointArray a ( samples + 10 ); int x = rect.width() - 2; for ( std::list<double>::reverse_iterator j = val.rbegin();j != val.rend() && x >= 2;j++ ) { if ( skip > 0 ) skip--; else { int val = int ( rect.height() - 2 - ( ( *j - zMinValue ) / ( zMaxValue - zMinValue ) * ( rect.height() - 4 ) ) ); x = rect.width() - 2 - count * ( rect.width() - 4 ) / ( samples - 1 ); a.setPoint ( count, x, val ); count++; if ( count >= samples ) break; } } a.resize ( count * 2 ); Points.insert ( Points.end(), a ); cp++; } } std::map<int, int> Bottom; for ( std::list<QPointArray>::iterator i = Points.begin();i != Points.end();i++ ) { QPointArray a = *i; int lx = 0; int lb = 0; for ( unsigned int j = 0;j < a.size() / 2;j++ ) { int x, y; a.point ( j, &x, &y ); if ( Bottom.find ( x ) == Bottom.end() ) Bottom[x] = 0; if ( lx != x ) lb = Bottom[x]; a.setPoint ( a.size() - 1 - j, x, zeroy - lb ); y -= lb; a.setPoint ( j, x, y ); Bottom[x] = zeroy - y; lx = x; } p->save(); /* p->setBrush(toChartColor(--cp)); */ p->drawPolygon ( a ); p->restore(); } }
/** Internal method that draws one of the pies in a pie chart. \param painter the QPainter to draw in \param dataset the dataset to draw the pie for \param pie the pie to draw \param the chart to draw the pie in \param regions a pointer to a list of regions that will be filled with regions representing the data segments, if not null */ void KDChartPiePainter::drawOnePie( QPainter* painter, KDChartTableDataBase* /*data*/, uint dataset, uint pie, uint chart, uint threeDPieHeight, KDChartDataRegionList* regions ) { // Is there anything to draw at all? int angleLen = _angleLens[ ( int ) pie ]; if ( angleLen ) { int startAngle = _startAngles[ ( int ) pie ]; KDChartDataRegion* datReg = 0; QRegion* region = 0; bool mustDeleteRegion = false; if ( regions ){ region = new QRegion(); mustDeleteRegion = true; } QRect drawPosition = _position; if ( params()->explode() ) { // need to compute a new position for each or some of the pie QValueList<int> explodeList = params()->explodeValues(); if( explodeList.count() == 0 || // nothing on list, explode all explodeList.find( pie ) != explodeList.end() ) { double explodeAngle = ( startAngle + angleLen / 2 ) / 16; double explodeAngleRad = DEGTORAD( explodeAngle ); double cosAngle = cos( explodeAngleRad ); double sinAngle = -sin( explodeAngleRad ); // find the explode factor for this particular pie double explodeFactor = 0.0; QMap<int,double> explodeFactors = params()->explodeFactors(); if( !explodeFactors.contains( pie ) ) // not on factors list, use default explodeFactor = params()->explodeFactor(); else // on factors list, use segment-specific value explodeFactor = explodeFactors[pie]; double explodeX = explodeFactor * _size * cosAngle; double explodeY = explodeFactor * _size * sinAngle; drawPosition.moveBy( static_cast<int>( explodeX ), static_cast<int>( explodeY ) ); } else drawPosition = _position; } else drawPosition = _position; // The 3D effect needs to be drawn first because it could // otherwise partly hide the pie itself. if ( params()->threeDPies() ) { draw3DEffect( painter, drawPosition, dataset, pie, chart, threeDPieHeight, params()->explode(), region ); } painter->setBrush( params()->dataColor( pie ) ); if ( angleLen == 5760 ) { // full circle, avoid nasty line in the middle painter->drawEllipse( drawPosition ); if ( regions ) { QPointArray hitregion; hitregion.makeEllipse( drawPosition.x(), drawPosition.y(), drawPosition.width(), drawPosition.height() ); datReg = new KDChartDataRegion( region->unite( QRegion( hitregion ) ), dataset, pie, chart ); datReg->points[ KDChartEnums::PosCenter ] = drawPosition.center(); datReg->points[ KDChartEnums::PosCenterRight ] = pointOnCircle( drawPosition, 0 ); datReg->points[ KDChartEnums::PosTopRight ] = pointOnCircle( drawPosition, 720 ); datReg->points[ KDChartEnums::PosTopCenter ] = pointOnCircle( drawPosition, 1440 ); datReg->points[ KDChartEnums::PosTopLeft ] = pointOnCircle( drawPosition, 2160 ); datReg->points[ KDChartEnums::PosCenterLeft ] = pointOnCircle( drawPosition, 2880 ); datReg->points[ KDChartEnums::PosBottomLeft ] = pointOnCircle( drawPosition, 3600 ); datReg->points[ KDChartEnums::PosBottomCenter ] = pointOnCircle( drawPosition, 4320 ); datReg->points[ KDChartEnums::PosBottomRight ] = pointOnCircle( drawPosition, 5040 ); datReg->startAngle = 2880; datReg->angleLen = 5760; regions->append( datReg ); } } else { // draw the top of this piece // Start with getting the points for the arc. const int arcPoints = angleLen; QPointArray collect(arcPoints+2); int i=0; for ( ; i<=angleLen; ++i){ collect.setPoint(i, pointOnCircle( drawPosition, startAngle+i )); } // Adding the center point of the piece. collect.setPoint(i, drawPosition.center() ); painter->drawPolygon( collect ); //if( bHelp ){ // painter->drawPolyline( collect ); //bHelp=false; //} if ( regions ) { QPointArray hitregion; hitregion.makeArc( drawPosition.x(), drawPosition.y(), drawPosition.width(), drawPosition.height(), ( int ) startAngle, ( int ) angleLen ); hitregion.resize( hitregion.size() + 1 ); hitregion.setPoint( hitregion.size() - 1, drawPosition.center() ); datReg = new KDChartDataRegion( region->unite( QRegion( hitregion ) ), dataset, pie, chart ); datReg->points[ KDChartEnums::PosTopLeft ] = pointOnCircle( drawPosition, startAngle + angleLen ); datReg->points[ KDChartEnums::PosTopCenter ] = pointOnCircle( drawPosition, startAngle + angleLen / 2 ); datReg->points[ KDChartEnums::PosTopRight ] = pointOnCircle( drawPosition, startAngle ); datReg->points[ KDChartEnums::PosBottomLeft ] = drawPosition.center(); datReg->points[ KDChartEnums::PosBottomCenter ] = datReg->points[ KDChartEnums::PosBottomLeft ]; datReg->points[ KDChartEnums::PosBottomRight ] = datReg->points[ KDChartEnums::PosBottomLeft ]; datReg->points[ KDChartEnums::PosCenterLeft ] = QPoint( ( datReg->points[ KDChartEnums::PosTopLeft ].x() + datReg->points[ KDChartEnums::PosBottomLeft ].x() ) / 2, ( datReg->points[ KDChartEnums::PosTopLeft ].y() + datReg->points[ KDChartEnums::PosBottomLeft ].y() ) / 2 ); datReg->points[ KDChartEnums::PosCenter ] = QPoint( ( datReg->points[ KDChartEnums::PosTopCenter ].x() + datReg->points[ KDChartEnums::PosBottomCenter ].x() ) / 2, ( datReg->points[ KDChartEnums::PosTopCenter ].y() + datReg->points[ KDChartEnums::PosBottomCenter ].y() ) / 2 ); datReg->points[ KDChartEnums::PosCenterRight ] = QPoint( ( datReg->points[ KDChartEnums::PosTopRight ].x() + datReg->points[ KDChartEnums::PosBottomRight ].x() ) / 2, ( datReg->points[ KDChartEnums::PosTopRight ].y() + datReg->points[ KDChartEnums::PosBottomRight ].y() ) / 2 ); datReg->startAngle = startAngle; datReg->angleLen = angleLen; regions->append( datReg ); } } if( mustDeleteRegion ) delete region; } }