void moveCanvas( int dx, int dy ) { if ( dx == 0 && dy == 0 ) return; if (!mPlot->isStopped()) dx = 0; for ( int axis = 0; axis < QwtPlot::axisCnt; axis++ ) { const QwtScaleMap map = mPlot->canvasMap( axis ); #if QWT_VERSION < 0x060102 const QwtScaleDiv* scaleDiv = mPlot->axisScaleDiv( axis ); #else const QwtScaleDiv* scaleDiv = &mPlot->axisScaleDiv( axis ); #endif const double p1 = map.transform( scaleDiv->lowerBound() ); const double p2 = map.transform( scaleDiv->upperBound() ); double d1, d2; if ( axis == QwtPlot::xBottom || axis == QwtPlot::xTop ) { d1 = map.invTransform( p1 - dx ); d2 = map.invTransform( p2 - dx ); } else { d1 = map.invTransform( p1 - dy ); d2 = map.invTransform( p2 - dy ); } mPlot->setAxisScale( axis, d1, d2 ); } mPlot->flagAxisSyncRequired(); mPlot->replot(); }
/// Compute curve offsets for a curve in a waterfall plot. /// @param xDataOffset :: Output value of an x-offset that should be applied to /// the data's bounding rect to fit to a waterfall plot. /// @param yDataOffset :: Output value of an y-offset that should be applied to /// the data's bounding rect to fit to a waterfall plot. void PlotCurve::computeWaterfallOffsets(double &xDataOffset, double &yDataOffset) { Plot *plot = static_cast<Plot *>(this->plot()); Graph *g = static_cast<Graph *>(plot->parent()); // Reset the offsets // These are offsets of the curve in pixels on the screen. d_x_offset = 0.0; d_y_offset = 0.0; if (g->isWaterfallPlot()) { int index = g->curveIndex(this); int curves = g->curves(); auto firstCurve = g->curve(0); // Get the minimum value of the first curve in this plot double ymin = firstCurve ? firstCurve->minYValue() : 0.0; PlotCurve *c = dynamic_cast<PlotCurve *>(g->curve(0)); if (index > 0 && c) { // Compute offsets based on the maximum value for the curve double xRange = plot->axisScaleDiv(Plot::xBottom)->range(); double yRange = plot->axisScaleDiv(Plot::yLeft)->range(); // First compute offsets in a linear scale xDataOffset = index * g->waterfallXOffset() * 0.01 * xRange / (double)(curves - 1); yDataOffset = index * g->waterfallYOffset() * 0.01 * yRange / (double)(curves - 1); // Corresponding offset on the screen in pixels d_x_offset = plot->canvas()->width() * xDataOffset / xRange; d_y_offset = plot->canvas()->height() * yDataOffset / yRange; // Correct the data offsets using actual axis scales. If the scales are // non-linear the offsets will change. { // x-offset auto trans = plot->axisScaleEngine(Plot::xBottom)->transformation(); auto a = trans->xForm(g->curve(0)->maxXValue(), plot->axisScaleDiv(Plot::xBottom)->lowerBound(), g->curve(0)->maxXValue(), 0, plot->canvas()->width()); auto b = trans->invXForm(a + d_x_offset, 0, plot->canvas()->width(), 1, g->curve(0)->maxXValue()); xDataOffset = b - g->curve(0)->maxXValue(); } { // y-offset auto trans = plot->axisScaleEngine(Plot::yLeft)->transformation(); auto a = trans->xForm(g->curve(0)->maxYValue(), plot->axisScaleDiv(Plot::yLeft)->lowerBound(), g->curve(0)->maxYValue(), 0, plot->canvas()->height()); auto b = trans->invXForm(a + d_y_offset, 0, plot->canvas()->height(), 1, g->curve(0)->maxYValue()); yDataOffset = b - g->curve(0)->maxYValue(); } // Set the z-order of the curves such that the first curve is on top. setZ(-index); // Fill down to minimum value of first curve setBaseline(ymin - yDataOffset); } else { // First curve - no offset. setZ(0); setBaseline(ymin); // This is for when 'fill under curve' is turn on xDataOffset = 0.0; yDataOffset = 0.0; } if (g->grid()) g->grid()->setZ(-g->curves() /*Count()*/ - 1); } }