QgsConstWkbPtr QgsSymbolV2::_getLineString( QPolygonF& pts, QgsRenderContext& context, QgsConstWkbPtr wkbPtr, bool clipToExtent ) { QgsWKBTypes::Type wkbType = wkbPtr.readHeader(); unsigned int nPoints; wkbPtr >> nPoints; const QgsCoordinateTransform* ct = context.coordinateTransform(); const QgsMapToPixel& mtp = context.mapToPixel(); //apply clipping for large lines to achieve a better rendering performance if ( clipToExtent && nPoints > 1 ) { const QgsRectangle& e = context.extent(); double cw = e.width() / 10; double ch = e.height() / 10; QgsRectangle clipRect( e.xMinimum() - cw, e.yMinimum() - ch, e.xMaximum() + cw, e.yMaximum() + ch ); wkbPtr -= 1 + 2 * sizeof( int ); wkbPtr = QgsClipper::clippedLineWKB( wkbPtr, clipRect, pts ); } else { pts.resize( nPoints ); int skipZM = ( QgsWKBTypes::coordDimensions( wkbType ) - 2 ) * sizeof( double ); Q_ASSERT( skipZM >= 0 ); QPointF *ptr = pts.data(); for ( unsigned int i = 0; i < nPoints; ++i, ++ptr ) { wkbPtr >> ptr->rx() >> ptr->ry(); wkbPtr += skipZM; } } //transform the QPolygonF to screen coordinates if ( ct ) { ct->transformPolygon( pts ); } QPointF *ptr = pts.data(); for ( int i = 0; i < pts.size(); ++i, ++ptr ) { mtp.transformInPlace( ptr->rx(), ptr->ry() ); } return wkbPtr; }
const QwtArray<QwtDoublePoint> & points) const #else QPolygonF QwtSplineCurveFitter::fitCurve(const QPolygonF &points) const #endif { const int size = (int)points.size(); if ( size <= 2 ) return points; FitMode fitMode = d_data->fitMode; if ( fitMode == Auto ) { fitMode = Spline; const QwtDoublePoint *p = points.data(); for ( int i = 1; i < size; i++ ) { if ( p[i].x() <= p[i-1].x() ) { fitMode = ParametricSpline; break; } }; } if ( fitMode == ParametricSpline ) return fitParametric(points); else return fitSpline(points); }
void UwMath::fromConformalInverted(QPolygonF &object) { QPointF * data = object.data(); for(int i = 0; i < object.size(); i++) { data[i].setX(UwMath::toDegrees(object.at(i).x())); data[i].setY(UwMath::fromMercator(object.at(i).y() * (-1))); } }
/** Converts a list of points from degrees to a conformal * point in Mercator projection * @param points in longitude, latitude given in degrees (DD) * @return conformal points in radians */ void UwMath::toConformal(QPolygonF &object) { QPointF * data = object.data(); for(int i = 0; i < object.size(); i++) { data[i].setX(UwMath::toRadians(object.at(i).x())); data[i].setY(UwMath::toMercator(object.at(i).y())); } }
QPolygonF QwtSplineCurveFitter::fitParametric( const QPolygonF &points ) const { int i; const int size = points.size(); QPolygonF fittedPoints( d_data->splineSize ); QPolygonF splinePointsX( size ); QPolygonF splinePointsY( size ); const QPointF *p = points.data(); QPointF *spX = splinePointsX.data(); QPointF *spY = splinePointsY.data(); double param = 0.0; for ( i = 0; i < size; i++ ) { const double x = p[i].x(); const double y = p[i].y(); if ( i > 0 ) { const double delta = qSqrt( qwtSqr( x - spX[i-1].y() ) + qwtSqr( y - spY[i-1].y() ) ); param += qMax( delta, 1.0 ); } spX[i].setX( param ); spX[i].setY( x ); spY[i].setX( param ); spY[i].setY( y ); } d_data->spline.setPoints( splinePointsX ); if ( !d_data->spline.isValid() ) return points; const double deltaX = splinePointsX[size - 1].x() / ( d_data->splineSize - 1 ); for ( i = 0; i < d_data->splineSize; i++ ) { const double dtmp = i * deltaX; fittedPoints[i].setX( qRound( d_data->spline.value( dtmp ) ) ); } d_data->spline.setPoints( splinePointsY ); if ( !d_data->spline.isValid() ) return points; const double deltaY = splinePointsY[size - 1].x() / ( d_data->splineSize - 1 ); for ( i = 0; i < d_data->splineSize; i++ ) { const double dtmp = i * deltaY; fittedPoints[i].setY( qRound( d_data->spline.value( dtmp ) ) ); } return fittedPoints; }
QPolygonF bezier_fit_cubic_single( const QPolygonF& data, double error ) { QPolygonF out(4); const int retn = sp_bezier_fit_cubic(out.data(), data.data(), data.count(), error); if( retn >= 0 ) return out; else return QPolygonF(); }
// we need a higher threshold for failure here than in the above tests, as this basically draws // a very thin outline, where the discretization in the new tesselator shows bool test_arc(const QPolygonF &poly, bool winding) { QVector<XTrapezoid> traps; qreal area1 = 0; qreal area2 = 0; old_tesselate_polygon(&traps, poly.data(), poly.size(), winding); area1 = compute_area_for_x(traps); traps.clear(); test_tesselate_polygon(&traps, poly.data(), poly.size(), winding); area2 = compute_area_for_x(traps); bool result = (area2 - area1 < .02); if (!result && area1) result = (qAbs(area1 - area2)/area1 < .02); return result; }
/*! \fn void QPaintEngine::drawEllipse(const QRectF &rect) Reimplement this function to draw the largest ellipse that can be contained within rectangle \a rect. The default implementation calls drawPolygon(). */ void QPaintEngine::drawEllipse(const QRectF &rect) { QPainterPath path; path.addEllipse(rect); if (hasFeature(PainterPaths)) { drawPath(path); } else { QPolygonF polygon = path.toFillPolygon(); drawPolygon(polygon.data(), polygon.size(), ConvexMode); } }
void QgsCoordinateTransform::transformPolygon( QPolygonF &poly, TransformDirection direction ) const { if ( !d->mIsValid || d->mShortCircuit ) { return; } //create x, y arrays int nVertices = poly.size(); QVector<double> x( nVertices ); QVector<double> y( nVertices ); QVector<double> z( nVertices ); double *destX = x.data(); double *destY = y.data(); double *destZ = z.data(); const QPointF *polyData = poly.constData(); for ( int i = 0; i < nVertices; ++i ) { *destX++ = polyData->x(); *destY++ = polyData->y(); *destZ++ = 0; polyData++; } try { transformCoords( nVertices, x.data(), y.data(), z.data(), direction ); } catch ( const QgsCsException & ) { // rethrow the exception QgsDebugMsg( QStringLiteral( "rethrowing exception" ) ); throw; } QPointF *destPoint = poly.data(); const double *srcX = x.constData(); const double *srcY = y.constData(); for ( int i = 0; i < nVertices; ++i ) { destPoint->rx() = *srcX++; destPoint->ry() = *srcY++; destPoint++; } }
QPolygonF bezier_fit_cubic_multi( const QPolygonF& data, double error, unsigned max_beziers ) { QPolygonF out(4*max_beziers); const int retn = sp_bezier_fit_cubic_r(out.data(), data.data(), data.count(), error, max_beziers); if( retn >= 0 ) { // get rid of unused points if( retn*4 < out.count() ) out.remove( retn*4, out.count()-retn*4 ); return out; } else return QPolygonF(); }
/*! Draw dots \param painter Painter \param xMap x map \param yMap y map \param canvasRect Contents rect of the canvas \param from index of the first point to be painted \param to index of the last point to be painted \sa draw(), drawCurve(), drawSticks(), drawLines(), drawSteps() */ void QwtPlotCurve::drawDots( QPainter *painter, const QwtScaleMap &xMap, const QwtScaleMap &yMap, const QRectF &canvasRect, int from, int to ) const { const bool doFill = d_data->brush.style() != Qt::NoBrush; const bool doAlign = QwtPainter::roundingAlignment( painter ); QPolygonF polyline; if ( doFill ) polyline.resize( to - from + 1 ); QPointF *points = polyline.data(); for ( int i = from; i <= to; i++ ) { const QPointF sample = d_series->sample( i ); double xi = xMap.transform( sample.x() ); double yi = yMap.transform( sample.y() ); if ( doAlign ) { xi = qRound( xi ); yi = qRound( yi ); } QwtPainter::drawPoint( painter, QPointF( xi, yi ) ); if ( doFill ) { points[i - from].rx() = xi; points[i - from].ry() = yi; } } if ( doFill ) { if ( d_data->paintAttributes & ClipPolygons ) polyline = QwtClipper::clipPolygonF( canvasRect, polyline ); fillCurve( painter, xMap, yMap, polyline ); } }
static PyObject *meth_QPolygonF_data(PyObject *sipSelf, PyObject *sipArgs) { PyObject *sipParseErr = NULL; { QPolygonF *sipCpp; if (sipParseArgs(&sipParseErr, sipArgs, "B", &sipSelf, sipType_QPolygonF, &sipCpp)) { void*sipRes; sipRes = sipCpp->data(); return sipConvertFromVoidPtr(sipRes); } } /* Raise an exception if the arguments couldn't be parsed. */ sipNoMethod(sipParseErr, sipName_QPolygonF, sipName_data, doc_QPolygonF_data); return NULL; }
/*! Draw a tube Builds 2 curves from the upper and lower limits of the intervals and draws them with the pen(). The area between the curves is filled with the brush(). \param painter Painter \param xMap Maps x-values into pixel coordinates. \param yMap Maps y-values into pixel coordinates. \param canvasRect Contents rect of the canvas \param from Index of the first sample to be painted \param to Index of the last sample to be painted. If to < 0 the series will be painted to its last sample. \sa drawSeries(), drawSymbols() */ void QwtPlotIntervalCurve::drawTube( QPainter *painter, const QwtScaleMap &xMap, const QwtScaleMap &yMap, const QRectF &canvasRect, int from, int to ) const { const bool doAlign = QwtPainter::roundingAlignment( painter ); painter->save(); const size_t size = to - from + 1; QPolygonF polygon( 2 * size ); QPointF *points = polygon.data(); for ( uint i = 0; i < size; i++ ) { QPointF &minValue = points[i]; QPointF &maxValue = points[2 * size - 1 - i]; const QwtIntervalSample intervalSample = sample( from + i ); if ( orientation() == Qt::Vertical ) { double x = xMap.transform( intervalSample.value ); double y1 = yMap.transform( intervalSample.interval.minValue() ); double y2 = yMap.transform( intervalSample.interval.maxValue() ); if ( doAlign ) { x = qRound( x ); y1 = qRound( y1 ); y2 = qRound( y2 ); } minValue.rx() = x; minValue.ry() = y1; maxValue.rx() = x; maxValue.ry() = y2; } else { double y = yMap.transform( intervalSample.value ); double x1 = xMap.transform( intervalSample.interval.minValue() ); double x2 = xMap.transform( intervalSample.interval.maxValue() ); if ( doAlign ) { y = qRound( y ); x1 = qRound( x1 ); x2 = qRound( x2 ); } minValue.rx() = x1; minValue.ry() = y; maxValue.rx() = x2; maxValue.ry() = y; } } if ( d_data->brush.style() != Qt::NoBrush ) { painter->setPen( QPen( Qt::NoPen ) ); painter->setBrush( d_data->brush ); if ( d_data->paintAttributes & ClipPolygons ) { const qreal m = 1.0; const QPolygonF p = QwtClipper::clipPolygonF( canvasRect.adjusted(-m, -m, m, m), polygon, true ); QwtPainter::drawPolygon( painter, p ); } else { QwtPainter::drawPolygon( painter, polygon ); } } if ( d_data->pen.style() != Qt::NoPen ) { painter->setPen( d_data->pen ); painter->setBrush( Qt::NoBrush ); if ( d_data->paintAttributes & ClipPolygons ) { QPolygonF p; p.resize( size ); qMemCopy( p.data(), points, size * sizeof( QPointF ) ); p = QwtClipper::clipPolygonF( canvasRect, p ); QwtPainter::drawPolyline( painter, p ); p.resize( size ); qMemCopy( p.data(), points + size, size * sizeof( QPointF ) ); p = QwtClipper::clipPolygonF( canvasRect, p ); QwtPainter::drawPolyline( painter, p ); } else { QwtPainter::drawPolyline( painter, points, size ); QwtPainter::drawPolyline( painter, points + size, size ); } } painter->restore(); }
// draw the ALT/SLOPE curve void AllPlotSlopeCurve::drawCurve( QPainter *painter, int, const QwtScaleMap &xMap, const QwtScaleMap &yMap, const QRectF &, int from, int to ) const { const QwtSeriesData<QPointF> *series = data(); // parameter (will move to data // use sensible defaults double section_delta = 0.1; bool byDistance = true; switch (d_data->style) { // time-section is defined in minutes, distance-section in km case SlopeTime1 : { section_delta = 1.0; byDistance = false; break; } case SlopeTime2 : { section_delta = 5.0; byDistance = false; break; } case SlopeTime3 : { section_delta = 10.0; byDistance = false; break; } case SlopeDist1 : { section_delta = 0.1; byDistance = true; break; } case SlopeDist2 : { section_delta = 0.5; byDistance = true; break; } case SlopeDist3 : { section_delta = 1; byDistance = true; break; } } // create single polygons to be painted (in different colors depending on slope) QList<QPolygonF*> polygons; // store the polygon edge points (original coordinates) for slope/distance & m/time calculation QList<QPointF> calcPoints; // prepare Y-Axis baseline info for painting the polygon double baseline = d_data->baseline; if ( yMap.transformation() ) baseline = yMap.transformation()->bounded( baseline ); double refY = yMap.transform( baseline ); double sectionStart = 0.0; QPolygonF *polygon; QPointF *points = NULL; for (int i = from; i <= to; i++ ) { const QPointF sample = series->sample( i ); if (i == from) { // first polygon polygon = new QPolygonF (4); points = polygon->data(); sectionStart = sample.x(); double xi = xMap.transform( sample.x() ); double yi = yMap.transform( sample.y() ); points[0].rx() = xi; points[0].ry() = refY; points[1].rx() = xi; points[1].ry() = yi; // first point for slope/mperh calcuation QPointF calcPoint; calcPoint.rx() = sample.x(); calcPoint.ry() = sample.y(); calcPoints.append(calcPoint); }; // we are in a section - so search for the end and if found close polygon if (points && sample.x() >= (sectionStart+section_delta)) { // we are at the end - close and create polygon and go to next double xi = xMap.transform( sample.x() ); double yi = yMap.transform( sample.y() ); points[2].rx() = xi; points[2].ry() = yi; points[3].rx() = xi; points[3].ry() = refY; // append to list polygons.append(polygon); // next point for slope/mperh calcuation QPointF calcPoint; calcPoint.rx() = sample.x(); calcPoint.ry() = sample.y(); calcPoints.append(calcPoint); // start the next polygon with the SAME point than the previous one to have a step-free graph polygon = new QPolygonF (4); points = polygon->data(); sectionStart = sample.x(); double xi2 = xMap.transform( sample.x() ); double yi2 = yMap.transform( sample.y() ); points[0].rx() = xi2; points[0].ry() = refY; points[1].rx() = xi2; points[1].ry() = yi2; } // last started polygon is not closed and painted by intent since it would be smaller than then the others } // paint the polygons & text per polygon int i = 0; foreach (QPolygonF *p, polygons) { double slope=0.0f; // slope of a section (byDistance = true) double mperh=0.0f; // meter per hour (climb or descent) (byDistance = false) QPointF point1 = calcPoints.at(i); QPointF point2 = calcPoints.at(i+1); QBrush brush; if (byDistance) { // if Y-Axis did not change, no calculation // distance - X-Axis is in KM, Y-Axis in m ! and at the end *100 to get %value if (point2.ry() != point1.ry()) { slope = 100 * ((point2.ry() - point1.ry()) / ((point2.rx() - point1.rx())*1000)); } else { slope = 0.0; } // set the brush if (slope >= 0 && slope < 5) brush = d_data->brushes[0]; if (slope >= 4 && slope < 7) brush = d_data->brushes[1]; if (slope >= 7 && slope < 10) brush = d_data->brushes[2]; if (slope >= 10 && slope < 15) brush = d_data->brushes[3]; if (slope >= 15) brush = d_data->brushes[4]; if (slope < 0 && slope > -2) brush = d_data->brushes[5]; if (slope <= -2 && slope > -5) brush = d_data->brushes[6]; if (slope <= -5 && slope > -9) brush = d_data->brushes[7]; if (slope <= -9 && slope > -15) brush = d_data->brushes[8]; if (slope <= -15) brush = d_data->brushes[5]; } else { // if Y-Axis did not change, no calculation // distance - X-Axis is in min, Y-Axis in m ! if (point2.ry() != point1.ry()) { mperh = 60 * ((point2.ry() - point1.ry()) / (point2.rx() - point1.rx())); } else { mperh = 0.0; } // set the brush if (mperh >= 0 && mperh < 100) brush = d_data->brushes[0]; if (mperh >= 100 && mperh < 200) brush = d_data->brushes[1]; if (mperh >= 200 && mperh < 300) brush = d_data->brushes[2]; if (mperh >= 300 && mperh < 500) brush = d_data->brushes[3]; if (mperh >= 500) brush = d_data->brushes[4]; if (mperh < 0 && mperh > -100) brush = d_data->brushes[5]; if (mperh <= -100 && mperh > -200) brush = d_data->brushes[6]; if (mperh <= -200 && mperh > -300) brush = d_data->brushes[7]; if (mperh <= -300 && mperh > -500) brush = d_data->brushes[8]; if (mperh <= -500) brush = d_data->brushes[5]; }; painter->setPen(QColor(127,127,127)); painter->setBrush( brush ); // paint the polygon QwtPainter::drawPolygon( painter, *p ); // determine Y-Width of polygon / don't show text if too small if (p->at(3).x() - p->at(0).x() > 25) { // draw the text (find the point, draw the text) QPointF pText = p->at(1); if (p->at(1).y() >= p->at(2).y()) pText.setY(p->at(2).y()); else pText.setY(p->at(1).y()); pText.rx() +=5.0; pText.ry() -=30.0; QString text; if (byDistance) { text.setNum(slope, 'f', 2); } else { text.setNum(mperh, 'f', 0); } painter->setPen(GCColor::invertColor(GColor(CPLOTBACKGROUND))); painter->setFont(QFont("Helvetica",8)); QwtPainter::drawText(painter, pText, text ); } i++; }
QgsConstWkbPtr QgsClipper::clippedLineWKB( QgsConstWkbPtr& wkbPtr, const QgsRectangle& clipExtent, QPolygonF& line ) { QgsWKBTypes::Type wkbType = wkbPtr.readHeader(); int nPoints; wkbPtr >> nPoints; int skipZM = ( QgsWKBTypes::coordDimensions( wkbType ) - 2 ) * sizeof( double ); if ( static_cast<int>( nPoints * ( 2 * sizeof( double ) + skipZM ) ) > wkbPtr.remaining() ) { QgsDebugMsg( QString( "%1 points exceed wkb length (%2>%3)" ).arg( nPoints ).arg( nPoints * ( 2 * sizeof( double ) + skipZM ) ).arg( wkbPtr.remaining() ) ); return QgsConstWkbPtr( nullptr, 0 ); } double p0x, p0y, p1x = 0.0, p1y = 0.0; //original coordinates double p1x_c, p1y_c; //clipped end coordinates double lastClipX = 0.0, lastClipY = 0.0; //last successfully clipped coords QPolygonF pts; wkbPtr -= sizeof( unsigned int ); wkbPtr >> pts; nPoints = pts.size(); line.clear(); line.reserve( nPoints + 1 ); QPointF *ptr = pts.data(); for ( int i = 0; i < nPoints; ++i, ++ptr ) { if ( i == 0 ) { p1x = ptr->rx(); p1y = ptr->ry(); continue; } else { p0x = p1x; p0y = p1y; p1x = ptr->rx(); p1y = ptr->ry(); p1x_c = p1x; p1y_c = p1y; if ( clipLineSegment( clipExtent.xMinimum(), clipExtent.xMaximum(), clipExtent.yMinimum(), clipExtent.yMaximum(), p0x, p0y, p1x_c, p1y_c ) ) { bool newLine = !line.isEmpty() && ( !qgsDoubleNear( p0x, lastClipX ) || !qgsDoubleNear( p0y, lastClipY ) ); if ( newLine ) { //add edge points to connect old and new line connectSeparatedLines( lastClipX, lastClipY, p0x, p0y, clipExtent, line ); } if ( line.size() < 1 || newLine ) { //add first point line << QPointF( p0x, p0y ); } //add second point lastClipX = p1x_c; lastClipY = p1y_c; line << QPointF( p1x_c, p1y_c ); } } } return wkbPtr; }
/*! \param points Series of data points \return Curve points */ QPolygonF QwtWeedingCurveFitter::fitCurve( const QPolygonF &points ) const { QStack<Line> stack; stack.reserve( 500 ); const QPointF *p = points.data(); const int nPoints = points.size(); QVector<bool> usePoint( nPoints, false ); double distToSegment; stack.push( Line( 0, nPoints - 1 ) ); while ( !stack.isEmpty() ) { const Line r = stack.pop(); // initialize line segment const double vecX = p[r.to].x() - p[r.from].x(); const double vecY = p[r.to].y() - p[r.from].y(); const double vecLength = qSqrt( vecX * vecX + vecY * vecY ); const double unitVecX = ( vecLength != 0.0 ) ? vecX / vecLength : 0.0; const double unitVecY = ( vecLength != 0.0 ) ? vecY / vecLength : 0.0; double maxDist = 0.0; int nVertexIndexMaxDistance = r.from + 1; for ( int i = r.from + 1; i < r.to; i++ ) { //compare to anchor const double fromVecX = p[i].x() - p[r.from].x(); const double fromVecY = p[i].y() - p[r.from].y(); const double fromVecLength = qSqrt( fromVecX * fromVecX + fromVecY * fromVecY ); if ( fromVecX * unitVecX + fromVecY * unitVecY < 0.0 ) { distToSegment = fromVecLength; } if ( fromVecX * unitVecX + fromVecY * unitVecY < 0.0 ) { distToSegment = fromVecLength; } else { const double toVecX = p[i].x() - p[r.to].x(); const double toVecY = p[i].y() - p[r.to].y(); const double toVecLength = qSqrt( toVecX * toVecX + toVecY * toVecY ); const double s = toVecX * ( -unitVecX ) + toVecY * ( -unitVecY ); if ( s < 0.0 ) distToSegment = toVecLength; else { distToSegment = qSqrt( qFabs( toVecLength * toVecLength - s * s ) ); } } if ( maxDist < distToSegment ) { maxDist = distToSegment; nVertexIndexMaxDistance = i; } } if ( maxDist <= d_data->tolerance ) { usePoint[r.from] = true; usePoint[r.to] = true; } else { stack.push( Line( r.from, nVertexIndexMaxDistance ) ); stack.push( Line( nVertexIndexMaxDistance, r.to ) ); } } int cnt = 0; QPolygonF stripped( nPoints ); for ( int i = 0; i < nPoints; i++ ) { if ( usePoint[i] ) stripped[cnt++] = p[i]; } stripped.resize( cnt ); return stripped; }
/*! Draw lines \param painter Painter \param azimuthMap Maps azimuth values to values related to 0.0, M_2PI \param radialMap Maps radius values into painter coordinates. \param pole Position of the pole in painter coordinates \param from index of the first point to be painted \param to index of the last point to be painted. \sa draw(), drawLines(), setCurveFitter() */ void QwtPolarCurve::drawLines( QPainter *painter, const QwtScaleMap &azimuthMap, const QwtScaleMap &radialMap, const QPointF &pole, int from, int to ) const { int size = to - from + 1; if ( size <= 0 ) return; QPolygonF polyline; if ( d_data->curveFitter ) { QPolygonF points( size ); for ( int j = from; j <= to; j++ ) { const QwtPointPolar point = sample( j ); points[j - from] = QPointF( point.azimuth(), point.radius() ); } points = d_data->curveFitter->fitCurve( points ); polyline.resize( points.size() ); QPointF *polylineData = polyline.data(); QPointF *pointsData = points.data(); for ( int i = 0; i < points.size(); i++ ) { const QwtPointPolar point( pointsData[i].x(), pointsData[i].y() ); double r = radialMap.transform( point.radius() ); const double a = azimuthMap.transform( point.azimuth() ); polylineData[i] = qwtPolar2Pos( pole, r, a ); } } else { polyline.resize( size ); QPointF *polylineData = polyline.data(); for ( int i = from; i <= to; i++ ) { QwtPointPolar point = sample( i ); if ( !qwtInsidePole( radialMap, point.radius() ) ) { double r = radialMap.transform( point.radius() ); const double a = azimuthMap.transform( point.azimuth() ); polylineData[i - from] = qwtPolar2Pos( pole, r, a ); } else { polylineData[i - from] = pole; } } } QRectF clipRect; if ( painter->hasClipping() ) clipRect = painter->clipRegion().boundingRect(); else { clipRect = painter->window(); if ( !clipRect.isEmpty() ) clipRect = painter->transform().inverted().mapRect( clipRect ); } if ( !clipRect.isEmpty() ) { double off = qCeil( qMax( 1.0, painter->pen().widthF() ) ); clipRect = clipRect.toRect().adjusted( -off, -off, off, off ); polyline = QwtClipper::clipPolygonF( clipRect, polyline ); } QwtPainter::drawPolyline( painter, polyline ); painter->drawPolyline( polyline ); }