コード例 #1
0
ファイル: PlotCurve.cpp プロジェクト: mantidproject/mantid
/// 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);
  }
}