bool QwtPlotZoomer::accept(QwtPolygon &pa) const
{
    if ( pa.count() < 2 )
        return false;

    QRect rect = QRect(pa[0], pa[int(pa.count()) - 1]);
#if QT_VERSION < 0x040000
    rect = rect.normalize();
#else
    rect = rect.normalized();
#endif

    const int minSize = 2;
    if (rect.width() < minSize && rect.height() < minSize )
        return false; 

    const int minZoomSize = 11;

    const QPoint center = rect.center();
    rect.setSize(rect.size().expandedTo(QSize(minZoomSize, minZoomSize)));
    rect.moveCenter(center);

    pa.resize(2);
    pa[0] = rect.topLeft();
    pa[1] = rect.bottomRight();

    return true;
}
inline static void addPoint(QwtPolygon &pa, uint pos, const QPoint &point)
{
    if ( uint(pa.size()) <= pos ) 
        pa.resize(pos + 5);

    pa.setPoint(pos, point);
}
inline void QwtPolygonClipper::addPoint(
    QwtPolygon &pa, uint pos, const QPoint &point) const
{
    if ( uint(pa.size()) <= pos ) 
        pa.resize(pos + 5);

    pa.setPoint(pos, point);
}
Example #4
0
/*!
  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 QwtDoublePoint &pole, int from, int to ) const
{
  int size = to - from + 1;
  if ( size <= 0 )
    return;

  QwtPolygon polyline;
  if ( d_data->curveFitter )
  {
#if QT_VERSION < 0x040000
    QwtArray<QwtDoublePoint> points( size );
#else
    QwtPolygonF points( size );
#endif
    for ( int j = from; j <= to; j++ )
      points[j - from] = QwtDoublePoint( azimuth( j ), radius( j ) );

    points = d_data->curveFitter->fitCurve( points );

    polyline.resize( points.size() );
    for ( int i = 0; i < ( int )points.size(); i++ )
    {
      const QwtPolarPoint point( points[i].x(), points[i].y() );

      double r = radialMap.xTransform( point.radius() );
      const double a = azimuthMap.xTransform( point.azimuth() );
      polyline.setPoint( i, qwtPolar2Pos( pole, r, a ).toPoint() );
    }
  }
  else
  {
    polyline.resize( size );

    for ( int i = from; i <= to; i++ )
    {
      const QwtPolarPoint point = sample( i );

      double r = radialMap.xTransform( point.radius() );
      const double a = azimuthMap.xTransform( point.azimuth() );
      polyline.setPoint( i - from, qwtPolar2Pos( pole, r, a ).toPoint() );
    }
  }

  QRect clipRect = painter->window();
  clipRect.setRect( clipRect.x() - 1, clipRect.y() - 1,
                    clipRect.width() + 2, clipRect.height() + 2 );

  polyline = QwtClipper::clipPolygon( clipRect, polyline );

  QwtPainter::drawPolyline( painter, polyline );
}
//! Sutherland-Hodgman polygon clipping
QwtPolygon QwtPolygonClipper::clipPolygon(const QwtPolygon &pa) const
{
    if ( contains( pa.boundingRect() ) )
        return pa;

    QwtPolygon cpa(pa.size());

    clipEdge((Edge)0, pa, cpa);

    for ( uint edge = 1; edge < NEdges; edge++ ) 
    {
        const QwtPolygon rpa = cpa;
#if QT_VERSION < 0x040000
        cpa.detach();
#endif
        clipEdge((Edge)edge, rpa, cpa);
    }

    return cpa;
}
Example #6
0
/*!
    Wrapper for QPainter::drawPolyline()
*/
void QwtPainter::drawPolyline(QPainter *painter, const QwtPolygon &pa)
{
    QRect clipRect;
    const bool deviceClipping = isClippingNeeded(painter, clipRect);

    QwtPolygon cpa = d_metricsMap.layoutToDevice(pa);
    if ( deviceClipping )
        cpa = QwtClipper::clipPolygon(clipRect, cpa);

#if QT_VERSION >= 0x040000
    bool doSplit = false;

    const QPaintEngine *pe = painter->paintEngine();
    if ( pe && pe->type() == QPaintEngine::Raster &&
        painter->pen().width() >= 2 )
    {
        /*
            The raster paint engine seems to use some algo with O(n*n).
            ( Qt 4.3 is better than Qt 4.2, but remains unacceptable)
            To work around this problem, we have to split the polygon into
            smaller pieces.
         */
        doSplit = true;
    }

    if ( doSplit )
    {
        const int numPoints = cpa.size();
        const QPoint *points = cpa.data();

        const int splitSize = 20;
        for ( int i = 0; i < numPoints; i += splitSize )
        {
            const int n = qwtMin(splitSize + 1, cpa.size() - i);
            painter->drawPolyline(points + i, n);
        }
    }
    else
#endif
        painter->drawPolyline(cpa);
}
Example #7
0
/**
 * When y-axis is clicked, the pixel coordinates are converted to graph coordinates, and displayed in a pop-up menu.
 * @param &y :: A reference to a click on the y-axis.
 */
void LabelTool::yAxisClicked(const QwtPolygon &y)
{
  populateMantidCurves();

  // Obtains the x value of the pixel coordinate.
  QPoint yy = y.point(0);
  int yPosition = yy.y();

  // Obtains the origins of the graph area and of the axis.
  QPoint canvasOrigin = d_graph->plotWidget()->canvas()->pos();
  int canvasOriginY = canvasOrigin.y();

  QPoint yOrigin = d_graph->plotWidget()->axisWidget(QwtPlot::yLeft)->pos();
  int yAxisOriginYValue = yOrigin.y();
  
/**
 * The difference in the origins is calculated then taken into account when converting the pixel coordinates of the
 * axis into graph coordinates.
 */

  int deltaOrigins = canvasOriginY - yAxisOriginYValue;
  int yPositionCorrected = yPosition - deltaOrigins;

  double yPos = d_graph->plotWidget()->invTransform(QwtPlot::yLeft, yPositionCorrected);
    
  if( yPos < 0)
  {
    return;
  }

  std::stringstream precisionValue;
  precisionValue.precision(6);
  precisionValue << yPos;
  m_yPosSigFigs = precisionValue.str();

  QMenu * clickMenu = new QMenu(d_graph);
  
  QAction * addYAxisLabel = new QAction(tr(QString::fromStdString(m_yPosSigFigs.c_str())), this);
  clickMenu->addAction(addYAxisLabel);
  connect(addYAxisLabel,SIGNAL(triggered()), this, SLOT(insertYCoord()));
  clickMenu->insertSeparator();

  clickMenu->exec(QCursor::pos());
}
Example #8
0
/**
 * When x-axis is clicked, the pixel coordinates are converted to graph
 * coordinates, and displayed in a pop-up menu.
 * @param &x :: A reference to a click on the x-axis.
 */
void LabelTool::xAxisClicked(const QwtPolygon &x) {
  populateMantidCurves();

  // Obtains the x value of the pixel coordinate.
  QPoint xx = x.point(0);
  int xPosition = xx.x();

  // Obtains the origins of the graph area and of the axis.
  QPoint canvasOrigin = d_graph->plotWidget()->canvas()->pos();
  int canvasOriginX = canvasOrigin.x();

  QPoint xOrigin = d_graph->plotWidget()->axisWidget(QwtPlot::xBottom)->pos();
  int xAxisOriginXValue = xOrigin.x();

  /**
   * The difference in the origins is calculated then taken into account when
   * converting the pixel coordinates of the
   * axis into graph coordinates.
   */

  int deltaOrigins = canvasOriginX - xAxisOriginXValue;
  int xPositionCorrected = xPosition - deltaOrigins;

  double xPos =
      d_graph->plotWidget()->invTransform(QwtPlot::xBottom, xPositionCorrected);

  if (xPos < 0) {
    return;
  }
  m_xPosSigFigs.setNum(xPos, 'f', 6);

  QMenu *clickMenu = new QMenu(d_graph);

  QAction *addXAxisLabel = new QAction(m_xPosSigFigs, this);
  clickMenu->addAction(addXAxisLabel);
  connect(addXAxisLabel, SIGNAL(triggered()), this, SLOT(insertXCoord()));

  clickMenu->exec(QCursor::pos());
}
/*! 
  Fill the area between the curve and the baseline with 
  the curve brush

  \param painter Painter
  \param xMap x map
  \param yMap y map
  \param pa Polygon

  \sa setBrush(), setBaseline(), setCurveType()
*/
void QwtPlotCurve::fillCurve(QPainter *painter,
    const QwtScaleMap &xMap, const QwtScaleMap &yMap,
    QwtPolygon &pa) const
{
    if ( d_data->brush.style() == Qt::NoBrush )
        return;

    closePolyline(xMap, yMap, pa);
    if ( pa.count() <= 2 ) // a line can't be filled
        return;

    QBrush b = d_data->brush;
    if ( !b.color().isValid() )
        b.setColor(d_data->pen.color());

    painter->save();

    painter->setPen(QPen(Qt::NoPen));
    painter->setBrush(b);

    QwtPainter::drawPolygon(painter, pa);

    painter->restore();
}
void QwtPolygonClipper::clipEdge(Edge edge, 
    const QwtPolygon &pa, QwtPolygon &cpa) const
{
    if ( pa.count() == 0 )
    {
        cpa.resize(0);
        return;
    }

    unsigned int count = 0;

    QPoint p1 = pa.point(0);
    if ( insideEdge(p1, edge) )
        addPoint(cpa, count++, p1);

    const uint nPoints = pa.size();
    for ( uint i = 1; i < nPoints; i++ )
    {
        const QPoint p2 = pa.point(i);
        if ( insideEdge(p2, edge) )
        {
            if ( insideEdge(p1, edge) )
                addPoint(cpa, count++, p2);
            else
            {
                addPoint(cpa, count++, intersectEdge(p1, p2, edge));
                addPoint(cpa, count++, p2);
            }
        }
        else
        {
            if ( insideEdge(p1, edge) )
                addPoint(cpa, count++, intersectEdge(p1, p2, edge));
        }
        p1 = p2;
    }
    cpa.resize(count);
}
/*!
  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 draw(), drawCurve(), drawSticks(), drawLines(), drawSteps()
*/
void QwtPlotCurve::drawDots(QPainter *painter,
    const QwtScaleMap &xMap, const QwtScaleMap &yMap, 
    int from, int to) const
{
    const QRect window = painter->window();
    if ( window.isEmpty() )
        return;

    const bool doFill = d_data->brush.style() != Qt::NoBrush;

    QwtPolygon polyline;
    if ( doFill )
        polyline.resize(to - from + 1);

    if ( to > from && d_data->paintAttributes & PaintFiltered )
    {
        if ( doFill )   
        {
            QPoint pp( xMap.transform(x(from)), yMap.transform(y(from)) );

            QwtPainter::drawPoint(painter, pp.x(), pp.y());
            polyline.setPoint(0, pp);

            int count = 1;
            for (int i = from + 1; i <= to; i++)
            {
                const QPoint pi(xMap.transform(x(i)), yMap.transform(y(i)));
                if ( pi != pp )
                {
                    QwtPainter::drawPoint(painter, pi.x(), pi.y());

                    polyline.setPoint(count, pi);
                    count++;

                    pp = pi;
                }
            }
            if ( int(polyline.size()) != count )
                polyline.resize(count);
        }
        else
        {
            // if we don't need to fill, we can sort out
            // duplicates independent from the order

            PrivateData::PixelMatrix pixelMatrix(window);

            for (int i = from; i <= to; i++)
            {
                const QPoint p( xMap.transform(x(i)),
                    yMap.transform(y(i)) );

                if ( pixelMatrix.testPixel(p) )
                    QwtPainter::drawPoint(painter, p.x(), p.y());
            }
        }
    }
    else
    {
        for (int i = from; i <= to; i++)
        {
            const int xi = xMap.transform(x(i));
            const int yi = yMap.transform(y(i));
            QwtPainter::drawPoint(painter, xi, yi);

            if ( doFill )
                polyline.setPoint(i - from, xi, yi);
        }
    }

    if ( doFill )
    {
        if ( d_data->paintAttributes & ClipPolygons )
            polyline = QwtClipper::clipPolygon(painter->window(), polyline);

        fillCurve(painter, xMap, yMap, polyline);
    }
}
/*!
  \brief Draw lines

  If the CurveAttribute Fitted is enabled a QwtCurveFitter tries
  to interpolate/smooth the curve, before it is painted.

  \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 setCurveAttribute(), setCurveFitter(), draw(), 
      drawLines(), drawDots(), drawSteps(), drawSticks()
*/
void QwtPlotCurve::drawLines(QPainter *painter,
    const QwtScaleMap &xMap, const QwtScaleMap &yMap, 
    int from, int to) const
{
    int size = to - from + 1;
    if ( size <= 0 )
        return;

    QwtPolygon polyline;
    if ( ( d_data->attributes & Fitted ) && d_data->curveFitter )
    {
        // Transform x and y values to window coordinates
        // to avoid a distinction between linear and
        // logarithmic scales.

#if QT_VERSION < 0x040000
        QwtArray<QwtDoublePoint> points(size);
#else
        QPolygonF points(size);
#endif
        for (int i = from; i <= to; i++)
        {
            QwtDoublePoint &p = points[i];
            p.setX( xMap.xTransform(x(i)) );
            p.setY( yMap.xTransform(y(i)) );
        }

        points = d_data->curveFitter->fitCurve(points);
        size = points.size();

        if ( size == 0 )
            return;

        // Round QwtDoublePoints to QPoints
        // When Qwt support for Qt3 has been dropped (Qwt 6.x)
        // we will use a doubles for painting and the following
        // step will be obsolete.

        polyline.resize(size);

        const QwtDoublePoint *p = points.data();
        QPoint *pl = polyline.data();
        if ( d_data->paintAttributes & PaintFiltered )
        {

            QPoint pp(qRound(p[0].x()), qRound(p[0].y()));
            pl[0] = pp;

            int count = 1;
            for (int i = 1; i < size; i++)
            {
                const QPoint pi(qRound(p[i].x()), qRound(p[i].y()));
                if ( pi != pp )
                {
                    pl[count++] = pi;
                    pp = pi;
                }
            }
            if ( count != size )
                polyline.resize(count);
        }
        else
        {
            for ( int i = 0; i < size; i++ )
            {
                pl[i].setX( qRound(p[i].x()) );
                pl[i].setY( qRound(p[i].y()) );
            }
        }
    }
    else
    {
        polyline.resize(size);

        if ( d_data->paintAttributes & PaintFiltered )
        {
            QPoint pp( xMap.transform(x(from)), yMap.transform(y(from)) );
            polyline.setPoint(0, pp);

            int count = 1;
            for (int i = from + 1; i <= to; i++)
            {
                const QPoint pi(xMap.transform(x(i)), yMap.transform(y(i)));
                if ( pi != pp )
                {
                    polyline.setPoint(count, pi);
                    count++;

                    pp = pi;
                }
            }
            if ( count != size )
                polyline.resize(count);
        }
        else
        {
            for (int i = from; i <= to; i++)
            {
                int xi = xMap.transform(x(i));
                int yi = yMap.transform(y(i));

                polyline.setPoint(i - from, xi, yi);
            }
        }
    }

    if ( d_data->paintAttributes & ClipPolygons )
        polyline = QwtClipper::clipPolygon(painter->window(), polyline);

    QwtPainter::drawPolyline(painter, polyline);

    if ( d_data->brush.style() != Qt::NoBrush )
        fillCurve(painter, xMap, yMap, polyline);
}
/*!
  \brief Complete a polygon to be a closed polygon 
         including the area between the original polygon
         and the baseline.
  \param xMap X map
  \param yMap Y map
  \param pa Polygon to be completed
*/
void QwtPlotCurve::closePolyline(
    const QwtScaleMap &xMap, const QwtScaleMap &yMap,
    QwtPolygon &pa) const
{
    const int sz = pa.size();
    if ( sz < 2 )
        return;

    pa.resize(sz + 2);

    if ( d_data->curveType == QwtPlotCurve::Xfy )
    {
        pa.setPoint(sz,
            xMap.transform(d_data->reference), pa.point(sz - 1).y());
        pa.setPoint(sz + 1,
            xMap.transform(d_data->reference), pa.point(0).y());
    }
    else
    {
        pa.setPoint(sz,
            pa.point(sz - 1).x(), yMap.transform(d_data->reference));
        pa.setPoint(pa.size() - 1,
            pa.point(0).x(), yMap.transform(d_data->reference));
    }
}
Example #14
0
/**
 * When the graph area is clicked, pixel coordinates are found and used to
 * determine graph coordinates.
 * Determines the number of MMCs from the list in populateMantidCurves().
 * For each MMC, determines whether a click on the graph area is within close
 * proximity to a data point.
 * If it is, the coordinates of the data point are stored for display.
 * @param &c :: A reference to a click on the graph area; it is bound by the x
 * and y-axis.
 */
void LabelTool::graphAreaClicked(const QwtPolygon &c) {
  populateMantidCurves();
  m_dataCoords.clear();

  QPoint cc = c.point(0);
  int xPosition = cc.x();
  int yPosition = cc.y();

  // std::cout << "xPosition: " << xPosition << " " << "yPosition: " <<
  // yPosition << '\n';

  m_xPos = d_graph->plotWidget()->invTransform(QwtPlot::xBottom, xPosition);
  m_yPos = d_graph->plotWidget()->invTransform(QwtPlot::yLeft, yPosition);

  // Sets the tolerance value, in pixels, for the range in which to search for a
  // data point.
  int tolerance = 7;

  foreach (MantidMatrixCurve *mantidMatrixCurve, m_mantidMatrixCurves) {
    // Sets the upper and lower limits in pixel coordinates for the x and
    // y-axes.
    int upperLimitX = xPosition + tolerance;
    int lowerLimitX = xPosition - tolerance;
    int upperLimitY = yPosition + tolerance;
    int lowerLimitY = yPosition - tolerance;

    /*
    // Gets the workspace name for which the curve belongs to.
    QString workspaceNameOfCurve = mantidMatrixCurve->workspaceName();
    */

    // Gets the number of data points on the curve.
    auto *mwd = mantidMatrixCurve->mantidData();
    size_t numberOfDataPoints = mwd->size();

    /**
    * Gets the pixel value of the x-coordinate value of each data point within
    * range.
    * Of the data points within range along x-axis, finds out if the pixel
    * values of their y-coordinates are within range.
    * If they are, their position within the iteration - i - is stored in a set.
    */

    QSet<size_t> pointsWithinRange;

    for (size_t i = 0; i < numberOfDataPoints; ++i) {
      // The pixel values of the x and y coordinates of the data points.
      int iPixelValueX =
          d_graph->plotWidget()->transform(QwtPlot::xBottom, mwd->x(i));
      int iPixelvalueY =
          d_graph->plotWidget()->transform(QwtPlot::yLeft, mwd->y(i));

      // Comparing the point of clicking with the positioning of the data
      // points.
      if (((iPixelValueX <= upperLimitX) && (iPixelValueX >= lowerLimitX)) &&
          ((iPixelvalueY <= upperLimitY) && (iPixelvalueY >= lowerLimitY))) {
        pointsWithinRange.insert(i);
      }
    }

    // If there are points within the specified ranges.
    if (!pointsWithinRange.isEmpty()) {
      /**
      * Uses Pythagoras' theorem to calculate the distance between the position
      * of a click and
      * the surrounding data points that lie within both the x and y ranges.
      */

      QMap<double, size_t> map;

      foreach (size_t i, pointsWithinRange) {
        double deltaX = m_xPos - mwd->x(i);
        double deltaY = m_yPos - mwd->y(i);
        double deltaXSquared = deltaX * deltaX;
        double deltaYSquared = deltaY * deltaY;

        double distance = sqrt(deltaXSquared + deltaYSquared);

        map[distance] = i;
      }