/*!
  Expand the selected rectangle to minZoomSize() and zoom in
  if accepted.

  \param ok If true, complete the selection and emit selected signals
            otherwise discard the selection.

  \sa accept(), minZoomSize()
  \return True if the selection has been accepted, false otherwise
*/
bool QwtPlotZoomer::end( bool ok )
{
    ok = QwtPlotPicker::end( ok );
    if ( !ok )
        return false;

    QwtPlot *plot = QwtPlotZoomer::plot();
    if ( !plot )
        return false;

    const QPolygon &pa = selection();
    if ( pa.count() < 2 )
        return false;

    QRect rect = QRect( pa.first(), pa.last() );
    rect = rect.normalized();

    const QwtScaleMap xMap = plot->canvasMap( xAxis() );
    const QwtScaleMap yMap = plot->canvasMap( yAxis() );

    QRectF zoomRect = QwtScaleMap::invTransform( xMap, yMap, rect ).normalized();

    zoomRect = qwtExpandedZoomRect( zoomRect, minZoomSize(),
        xMap.transformation(), yMap.transformation() );

    zoom( zoomRect );

    return true;
}
Esempio n. 2
0
QDebug operator<<( QDebug debug, const QwtScaleMap &map )
{
    debug.nospace() << "QwtScaleMap("
        << static_cast<int>( map.transformation()->type() )
        << ", s:" << map.s1() << "->" << map.s2()
        << ", p:" << map.p1() << "->" << map.p2()
        << ")";

    return debug.space();
}
Esempio n. 3
0
/*!
  \brief Complete a polygon to be a closed polygon including the 
         area between the original polygon and the baseline.

  \param painter Painter
  \param xMap X map
  \param yMap Y map
  \param polygon Polygon to be completed
*/
void QwtPlotCurve::closePolyline( QPainter *painter,
    const QwtScaleMap &xMap, const QwtScaleMap &yMap,
    QPolygonF &polygon ) const
{
    if ( polygon.size() < 2 )
        return;

    const bool doAlign = QwtPainter::roundingAlignment( painter );

    double baseline = d_data->baseline;
    
    if ( orientation() == Qt::Vertical )
    {
        if ( yMap.transformation()->type() == QwtScaleTransformation::Log10 )
        {
            if ( baseline < QwtScaleMap::LogMin )
                baseline = QwtScaleMap::LogMin;
        }

        double refY = yMap.transform( baseline );
        if ( doAlign )
            refY = qRound( refY );

        polygon += QPointF( polygon.last().x(), refY );
        polygon += QPointF( polygon.first().x(), refY );
    }
    else
    {
        if ( xMap.transformation()->type() == QwtScaleTransformation::Log10 )
        {
            if ( baseline < QwtScaleMap::LogMin )
                baseline = QwtScaleMap::LogMin;
        }

        double refX = xMap.transform( baseline );
        if ( doAlign )
            refX = qRound( refX );

        polygon += QPointF( refX, polygon.last().y() );
        polygon += QPointF( refX, polygon.first().y() );
    }
}
/*!
  \brief Draw the scale
*/
void QwtPlotScaleItem::draw( QPainter *painter,
    const QwtScaleMap &xMap, const QwtScaleMap &yMap,
    const QRectF &canvasRect ) const
{
    QwtScaleDraw *sd = d_data->scaleDraw;

    if ( d_data->scaleDivFromAxis )
    {
        const QwtInterval interval = 
            d_data->scaleInterval( canvasRect, xMap, yMap );

        if ( interval != sd->scaleDiv().interval() )
        {
            QwtScaleDiv scaleDiv = sd->scaleDiv();
            scaleDiv.setInterval( interval );
            sd->setScaleDiv( scaleDiv );
        }
    }

    QPen pen = painter->pen();
    pen.setStyle( Qt::SolidLine );
    painter->setPen( pen );

    if ( sd->orientation() == Qt::Horizontal )
    {
        double y;
        if ( d_data->borderDistance >= 0 )
        {
            if ( sd->alignment() == QwtScaleDraw::BottomScale )
                y = canvasRect.top() + d_data->borderDistance;
            else
            {
                y = canvasRect.bottom() - d_data->borderDistance;
            }

        }
        else
        {
            y = yMap.transform( d_data->position );
        }

        if ( y < canvasRect.top() || y > canvasRect.bottom() )
            return;

        sd->move( canvasRect.left(), y );
        sd->setLength( canvasRect.width() - 1 );

        QwtTransform *transform = NULL;
        if ( xMap.transformation() )
            transform = xMap.transformation()->copy();

        sd->setTransformation( transform );
    }
    else // == Qt::Vertical
    {
        double x;
        if ( d_data->borderDistance >= 0 )
        {
            if ( sd->alignment() == QwtScaleDraw::RightScale )
                x = canvasRect.left() + d_data->borderDistance;
            else
            {
                x = canvasRect.right() - d_data->borderDistance;
            }
        }
        else
        {
            x = xMap.transform( d_data->position );
        }
        if ( x < canvasRect.left() || x > canvasRect.right() )
            return;

        sd->move( x, canvasRect.top() );
        sd->setLength( canvasRect.height() - 1 );

        QwtTransform *transform = NULL;
        if ( yMap.transformation() )
            transform = yMap.transformation()->copy();

        sd->setTransformation( transform );
    }

    painter->setFont( d_data->font );

    sd->draw( painter, d_data->palette );
}
Esempio n. 5
0
/*!
   Update the axis scale draw geometries

   \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 radius Radius of the complete plot area in painter coordinates

   \sa updateScaleDiv()
*/
void QwtPolarGrid::updateScaleDraws(
  const QwtScaleMap &azimuthMap, const QwtScaleMap &radialMap,
  const QwtDoublePoint &pole, double radius ) const
{
  const QPoint p = pole.toPoint();

  const QwtDoubleInterval interval =
    d_data->gridData[QwtPolar::ScaleRadius].scaleDiv.interval();

  const int min = radialMap.transform( interval.minValue() );
  const int max = radialMap.transform( interval.maxValue() );
  const int l = max - min;

  for ( int axisId = 0; axisId < QwtPolar::AxesCount; axisId++ )
  {
    AxisData &axis = d_data->axisData[axisId];

    if ( axisId == QwtPolar::AxisAzimuth )
    {
      QwtRoundScaleDraw *scaleDraw = ( QwtRoundScaleDraw * )axis.scaleDraw;

      scaleDraw->setRadius( qRound( radius ) );
      scaleDraw->moveCenter( p );

      double from = ::fmod( 90.0 - azimuthMap.p1() * 180.0 / M_PI, 360.0 );
      if ( from < 0.0 )
        from += 360.0;

      scaleDraw->setAngleRange( from, from - 360.0 );
      scaleDraw->setTransformation( azimuthMap.transformation()->copy() );
    }
    else
    {
      QwtScaleDraw *scaleDraw = ( QwtScaleDraw * )axis.scaleDraw;
      switch ( axisId )
      {
        case QwtPolar::AxisLeft:
        {
          scaleDraw->move( p.x() - min, p.y() );
          scaleDraw->setLength( -l );
          break;
        }
        case QwtPolar::AxisRight:
        {
          scaleDraw->move( p.x() + min, p.y() );
          scaleDraw->setLength( l );
          break;
        }
        case QwtPolar::AxisTop:
        {
          scaleDraw->move( p.x(), p.y() - max );
          scaleDraw->setLength( l );
          break;
        }
        case QwtPolar::AxisBottom:
        {
          scaleDraw->move( p.x(), p.y() + max );
          scaleDraw->setLength( -l );
          break;
        }
      }
      scaleDraw->setTransformation( radialMap.transformation()->copy() );
    }
  }
}
/*!
  \brief Draw the scale
*/
void QwtPlotScaleItem::draw(QPainter *painter, 
    const QwtScaleMap &xMap, const QwtScaleMap &yMap,
    const QRect &canvasRect) const
{
    if ( canvasRect != d_data->canvasRectCache )
    {
        QwtPlotScaleItem* that = (QwtPlotScaleItem*)this;
        that->updateBorders();
    }

    QPen pen = painter->pen();
    pen.setStyle(Qt::SolidLine);
    painter->setPen(pen);

    int pw = painter->pen().width();
    if ( pw == 0 )
        pw = 1;

    QwtScaleDraw *sd = d_data->scaleDraw;
    if ( sd->orientation() == Qt::Horizontal )
    {
        int y;
        if ( d_data->borderDistance >= 0 )
        {
            if ( sd->alignment() == QwtScaleDraw::BottomScale )
                y = canvasRect.top() + d_data->borderDistance;
            else
            {
                y = canvasRect.bottom() - d_data->borderDistance - pw + 1;
            }

        }
        else
        {
            y = yMap.transform(d_data->position);
        }

        if ( y < canvasRect.top() || y > canvasRect.bottom() )
            return;

        sd->move(canvasRect.left(), y);
        sd->setLength(canvasRect.width() - 1);
        sd->setTransformation(xMap.transformation()->copy());
    }
    else // == Qt::Vertical
    {
        int x;
        if ( d_data->borderDistance >= 0 )
        {
            if ( sd->alignment() == QwtScaleDraw::RightScale )
                x = canvasRect.left() + d_data->borderDistance;
            else
            {
                x = canvasRect.right() - d_data->borderDistance - pw + 1;
            }
        }
        else
        {
            x = xMap.transform(d_data->position);
        }
        if ( x < canvasRect.left() || x > canvasRect.right() )
            return;

        sd->move(x, canvasRect.top());
        sd->setLength(canvasRect.height() - 1);
        sd->setTransformation(yMap.transformation()->copy());
    }

    painter->setFont(d_data->font);

#if QT_VERSION < 0x040000
    sd->draw(painter, d_data->colorGroup);
#else
    sd->draw(painter, d_data->palette);
#endif
    
}
// 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++;
    }
void PlotMagnifier::rescale( double factor, AxisMode axis )
{
    factor = qAbs( 1.0/factor );

    QwtPlot* plt = plot();
    if ( plt == nullptr || factor == 1.0 ){
        return;
    }

    bool doReplot = false;

    const bool autoReplot = plt->autoReplot();
    plt->setAutoReplot( false );

    const int axis_list[2] = {QwtPlot::xBottom, QwtPlot::yLeft};
    QRectF new_rect;

    for ( int i = 0; i <2; i++ )
    {
        double temp_factor = factor;
        if( i==1 && axis == X_AXIS)
        {
            temp_factor = 1.0;
        }
        if( i==0 && axis == Y_AXIS)
        {
            temp_factor = 1.0;
        }

        int axisId = axis_list[i];

        if ( isAxisEnabled( axisId ) )
        {
            const QwtScaleMap scaleMap = plt->canvasMap( axisId );

            double v1 = scaleMap.s1();
            double v2 = scaleMap.s2();
            double center = _mouse_position.x();

            if( axisId == QwtPlot::yLeft){
                center = _mouse_position.y();
            }

            if ( scaleMap.transformation() )
            {
                // the coordinate system of the paint device is always linear
                v1 = scaleMap.transform( v1 ); // scaleMap.p1()
                v2 = scaleMap.transform( v2 ); // scaleMap.p2()
            }

            const double width = ( v2 - v1 );
            const double ratio = (v2-center)/ (width);

            v1 = center - width*temp_factor*(1-ratio);
            v2 = center + width*temp_factor*(ratio);

            if( v1 > v2 ) std::swap( v1, v2 );

            if ( scaleMap.transformation() )
            {
                v1 = scaleMap.invTransform( v1 );
                v2 = scaleMap.invTransform( v2 );
            }

            if( v1 < _lower_bounds[axisId]) v1 = _lower_bounds[axisId];
            if( v2 > _upper_bounds[axisId]) v2 = _upper_bounds[axisId];

            plt->setAxisScale( axisId, v1, v2 );

            if( axisId == QwtPlot::xBottom)
            {
                new_rect.setLeft(  v1 );
                new_rect.setRight( v2 );
            }
            else{
                new_rect.setBottom( v1 );
                new_rect.setTop( v2 );
            }

            doReplot = true;
        }
    }

    plt->setAutoReplot( autoReplot );

    if ( doReplot ){
        emit rescaled( new_rect );
    }
}