void ClusterView::customEvent(QCustomEvent* event){ if(event->type() == QEvent::User + 700){ QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); ComputeEvent* computeEvent = (ComputeEvent*) event; //Get the polygon QPointArray polygon = computeEvent->polygon(); QRegion selectionArea; QPointArray reviewPolygon; long Xdimension = 0; long Ydimension = 0; //The QRegion uses rectangles to define its area and the number of rectangles //increases with the height of the region (y axis). The more rectangles the longer //the search of one point in the region will take. With a dimension like the time //the height has an order of the millon (at least 5 going to 80 or more) given a huge amount //of rectangles. A way of speeding the search of points is to reduce the number of rectangles. //To do so, if the y dimension is the time, x and y axis are inverted. //Caution: in Qt graphical coordinate system, the Y axis is inverted (increasing downwards), //thus a point (x,y) is drawn as (x,-y), before creating the region the points are reset to there raw value (x,y). if(view.ordinateDimension() != timeDimension){ for(uint i = 0; i< polygon.size();++i){ reviewPolygon.putPoints(i, 1,polygon.point(i).x(),-polygon.point(i).y()); Xdimension = dimensionX; Ydimension = dimensionY; } } else{ for(uint i = 0; i< polygon.size();++i){ reviewPolygon.putPoints(i, 1,-polygon.point(i).y(),polygon.point(i).x()); Xdimension = dimensionY; Ydimension = dimensionX; } } //Create a QRegion with the new selection area in order to use the research facilities offer by a QRegion. selectionArea = QRegion(reviewPolygon); if(!selectionArea.isNull()){ //Call any appropriate method switch(mode){ case DELETE_NOISE: doc.deleteNoise(selectionArea,view.clusters(),Xdimension,Ydimension); break; case DELETE_ARTEFACT: doc.deleteArtifact(selectionArea,view.clusters(),Xdimension,Ydimension); break; case NEW_CLUSTER: doc.createNewCluster(selectionArea,view.clusters(),Xdimension,Ydimension); break; case NEW_CLUSTERS: doc.createNewClusters(selectionArea,view.clusters(),Xdimension,Ydimension); break; case ZOOM: break; //nothing to do } } QApplication::restoreOverrideCursor(); } }
QPoint Reversi::ai(const int player) { const int choices[8][8] = { {100, -100, 50, 30, 30, 50, -100, 100,}, {-100, -100, -50, -50, -50, -50, -100, -100,}, {50, -50, 10, 10, 10, 10, -50, 50,}, {30, -50, 10, 0, 0, 10, -50, 30,}, {30, -50, 10, 0, 0, 10, -50, 30,}, {50, -50, 10, 10, 10, 10, -50, 50,}, {-100, -100, -50, -50, -50, -50, -100, -100,}, {100, -100, 50, 30, 30, 50, -100, 100,}, }; QPointArray spaces = availableSpaces(player); if (spaces.size() == 0) return BoardGame::ai(player); int values[spaces.size()]; for (unsigned int i = 0; i < spaces.size(); i++) { QPoint p(spaces[i]); values[i] = choices[p.y()][p.x()] + reversible(p, player) * 5; } int max = 0; for (unsigned int i = 0; i < spaces.size(); i++) if (values[i] > values[max]) max = i; QList<int> equals; equals.setAutoDelete(true); for (unsigned int i = 0; i < spaces.size(); i++) if (values[i] == values[max]) equals.append(new int(i)); return spaces[*equals.at(rand() % equals.count())]; }
QRegion::QRegion( const QPointArray &a, bool winding ) { data = new QRegionData; Q_CHECK_PTR( data ); data->hgt = 0; data->is_null = FALSE; QRect r = a.boundingRect(); if ( a.isEmpty() || r.isEmpty() ) { data->rgn = 0; } else { HPS hps = qt_display_ps(); POINTL *pts = new POINTL[ a.size() ]; for ( uint i = 0; i < a.size(); ++ i ) { pts[i].x = a[i].x(); pts[i].y = - (a[i].y() + 1); } // GpiCreatePolygonRegion() is bogus and always starts a poligon from // the current position. Make the last point the current one and reduce // the number of points by one. GpiMove( hps, &pts[ a.size() - 1 ] ); POLYGON poly = { a.size() - 1, pts }; ULONG opts = winding ? POLYGON_WINDING : POLYGON_ALTERNATE; data->rgn = GpiCreatePolygonRegion( hps, 1, &poly, opts ); delete[] pts; } }
QRegion::QRegion( const QRect &r, RegionType t ) { data = new QRegionData; Q_CHECK_PTR( data ); data->hgt = 0; data->is_null = FALSE; if ( r.isEmpty() ) { data->rgn = 0; } else { HPS hps = qt_display_ps(); if ( t == Rectangle ) { // rectangular region RECTL rcl = { r.left(), -(r.bottom()+1), r.right()+1, -r.top() }; data->rgn = GpiCreateRegion( hps, 1, &rcl ); } else if ( t == Ellipse ) { // elliptic region // if the width or height of the ellipse is odd, GPI always // converts it to a nearest even value, which is obviously stupid // (see also QPainter::drawArcInternal()). So, we don't use // GpiCreateEllipticRegion(), but create an array of points to // call GpiCreatePolygonRegion() instead. QPointArray a; a.makeArc( r.x(), r.y(), r.width(), r.height(), 0, 360 * 16 ); for ( uint i = 0; i < a.size(); ++ i ) a[i].ry() = -(a[i].y() + 1); // GpiCreatePolygonRegion() is bogus and always starts a poligon from // the current position. Make the last point the current one and reduce // the number of points by one. GpiMove( hps, (PPOINTL) &a[ a.size() - 1 ] ); POLYGON poly = { a.size() - 1, (PPOINTL) a.data() }; data->rgn = GpiCreatePolygonRegion( hps, 1, &poly, POLYGON_ALTERNATE ); } } }
QRegion::QRegion( const QPointArray &a, bool winding ) { data = new QRegionData; CHECK_PTR( data ); data->is_null = FALSE; data->rgn = XPolygonRegion( (XPoint*)a.data(), a.size(), winding ? WindingRule : EvenOddRule ); }
QPointArray Reversi::availableSpaces(const int player) const { QPointArray spaces; for (int r = 0; r < size().height(); r++) for (int c = 0; c < size().width(); c++) if (available(QPoint(c, r), player)) spaces.putPoints(spaces.size(), 1, c, r); return spaces; }
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; }
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 KIconEditGrid::drawPointArray(QPointArray a, DrawAction action) { QRect rect = a.boundingRect(); bool update = false; int s = a.size(); //((rect.size().width()) * (rect.size().height())); for(int i = 0; i < s; i++) { int x = a[i].x(); int y = a[i].y(); //if(img->valid(x, y) && !QSize(x, y).isNull() && rect.contains(QPoint(x, y))) if(img->valid(x, y) && rect.contains(QPoint(x, y))) { //debug("x: %d - y: %d", x, y); switch( action ) { case Draw: { *((uint*)img->scanLine(y) + x) = currentcolor; //colors[cell]|OPAQUE; int cell = y * numCols() + x; setColor( cell, currentcolor, false ); modified = true; update = true; //updateCell( y, x, FALSE ); break; } case Mark: case UnMark: repaint(x*cellsize,y*cellsize, cellsize, cellsize, false); //updateCell( y, x, true ); break; default: break; } } } if(update) { updateColors(); repaint(rect.x()*cellSize()-1, rect.y()*cellSize()-1, rect.width()*cellSize()+1, rect.height()*cellSize()+1, false); pntarray.resize(0); } }
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(); }
void KviCanvasView::beginDragPolygon(KviCanvasPolygon * it,const QPoint &p,bool bShift,bool bCtrl) { m_dragBegin = QPoint((int)(p.x() - it->x()),(int)(p.y() - it->y())); QPointArray pa = it->areaPoints(); for(unsigned int i=0;i<pa.size();i++) { QPoint pnt = pa.point(i); double dX = pnt.x() - p.x(); double dY = pnt.y() - p.y(); double dHypot = sqrt((dX * dX) + (dY * dY)); if(dHypot < 3.0) { // We're dragging a point m_dragMode = SinglePoint; m_dragPointIndex = i; setCursor(crossCursor); return; } } if(bShift) { m_dragMode = Scale; m_dragScaleFactor = it->scaleFactor(); setCursor(sizeAllCursor); return; } if(bCtrl) { m_dragMode = Rotate; m_dragPointArray = it->internalPoints(); // qDebug("Here"); setCursor(sizeHorCursor); return; } m_dragMode = All; setCursor(pointingHandCursor); }
QRegion::QRegion( const QRect &r, RegionType t ) { QRect rr = r.normalize(); data = new QRegionData; CHECK_PTR( data ); data->is_null = FALSE; if ( t == Rectangle ) { // rectangular region data->rgn = XCreateRegion(); XRectangle xr; xr.x = rr.x(); xr.y = rr.y(); xr.width = rr.width(); xr.height = rr.height(); XUnionRectWithRegion( &xr, data->rgn, data->rgn ); } else if ( t == Ellipse ) { // elliptic region QPointArray a; a.makeEllipse( rr.x(), rr.y(), rr.width(), rr.height() ); data->rgn = XPolygonRegion( (XPoint*)a.data(), a.size(), EvenOddRule ); } }
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 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; } }