yphysToYscreen method

double yphysToYscreen (double y)

Converts physical y coordinate to screen y coordinate, which is returned relative to the data area. Formula: see .odt document in specpad source tree in the folder "manuals". have the type of PhysicalToScreen.

Implementation

double yphysToYscreen(double y) {
  double yscreen;
  int he = effectivePolylineHeight;

  if (zoomRegion != null) {
    double a2, b2;
    if ((zoomRegion.ybottom - zoomRegion.ytop).abs() < 0.000001) {
      a2 = 1.0; // TODO right?
      b2 = -he / 2;
//        yscale = 1.0; // ori
    } else {
      a2 = -he / (zoomRegion.ybottom - zoomRegion.ytop);
      b2 = insety + a2 * zoomRegion.ytop; // ori
    }
    yscale = 1.0;
    yshift1 = 0;
    attr[PyA.YSHIFT1] = "0";
    attr[PyA.YSCALE] = "1.0";
//      double yzero = double.parse(attributes[PyA.YPOSITION_ZERO]);
//      yzero = yzero - b2/effectivePolylineHeight;
//      attributes[PyA.YPOSITION_ZERO] = "${yzero}";
//      yscreen = -a2*y*yscale + b2; //ori

//      b2=yzero*effectivePolylineHeight+insety;
    yscreen = -a2 * y + b2;

//      int hr = zoomRegion.ysbottom - zoomRegion.ystop;
//      a = (hr/he) * a2;
//      b = (hr/he)*(b2 - insety) + zoomRegion.ystop;
    a = a2;
    b = b2; // ori
//      a = a2*yscale; b = b2;
  } else {
    // screen position of polyline value 0 point in % of effective view height: 0.5 means centered.
    double ysLeft = double.parse(attr[PyA.YPOSITION_ZERO]); // orig
    double yix1 = double.parse(attr[PyA.YIX1]);
    double ys1, ys2, yix2;

    // yscale is the accumulated user interactive mouse wheel scaling factor
    // the next line ensures that "a", which is proportional to (c1-c2), does not change sign.
    // Otherwise, after turning the mouse wheel too much, the spectrum would change sign and
    // would be drawn upside down.
    double c1 = ysLeft; // e.g.0.9 for spectra, 0.5 for fids
    // c2 = 0 means ymax will be displayed at "insety":
    double c2 = POLYLINE_INITIAL_YSCALE - yscale;
    // ensure ys will not become 0 or even change sign when yscale too large:
    if (c2 > c1) c2 = c1 - 0.01;
    ys1 = c1 * he + insety; // screen pos. of leftmost point in region
    ys2 = c2 * he + insety; // screen pos. of ymax in region

    // This code defines that PyA.YPOSITION_ZERO is the rel. y position
    // of the point y=0 of the data. One could also set yix1 = yValues[0] or
    // yix1 = yValues[ixFirst] or ... (see PyA.YIX1)
    // to define another point to take on PyA.YPOSITION_ZERO.
    // The current solution works best for spectra, fids.
    if (ymin < 0 && ymax < 0) {
      // spectra with only negative values need special treatment for correct
      // display: must invert all y values before computing screen coord.
      y = -y;
      double temp = -ymax;
      ymax = -ymin;
      ymin = temp;
      yix1 = 0.0; // phys. y of ys1 (could be different for diff. y offset)
      yix2 = ymax; // phys. y of ys2
    } else {
      // "normal" spectra with mixed positive and negative y values
      yix1 = 0.0; // phys. y of ys1
      yix2 = ymax; // phys. y of ys2
    }

    if ((yix2 - yix1).abs() < 0.000001 && y * yscale.abs() < 0.000001) {
      // y == ymax, treat singular case for y = 0
      a = 0.0; // TODO
    } else if ((yix2 - yix1).abs() < 0.000001) {
      // y == ymax, treat remaining singular case for y != 0
      a = 0.0; // TODO
    } else {
      a = -(ys2 - ys1) / (yix2 - yix1);
    }

    b = ys1 + a * yix1 + yshift1 + yshift2;
    yscreen = -a * y + b;
  }

  try {
    yscreen.round(); // test, except, if failed
    return yscreen;
  } catch (e) {
    // e.g. when zooming a data set containing only zeroes
    return dataAreaHeight / 2;
  }
}