Commit df6fdab4 authored by Ian Humphrey's avatar Ian Humphrey
Browse files

Spectral Plot Tool now computes statistics more accurately. Fixes #2071.

git-svn-id: http://subversion.wr.usgs.gov/repos/prog/isis3/trunk@5934 41f8697f-d340-4b68-9986-7bafba869bb8
parent 1ef91920
Loading
Loading
Loading
Loading
+32 −21
Original line number Diff line number Diff line
@@ -27,8 +27,8 @@ using std::cerr;
namespace Isis {

  /**
   * This constructs a plot tool. The plot tool graphs either DN values across a
   * line, or statistics across a spectrum (bands).
   * This constructs a spectral plot tool. The spectral plot tool graphs statistics across a 
   * spectrum (bands).
   *
   *
   * @param parent
@@ -45,6 +45,9 @@ namespace Isis {
    m_toolPadAction = new QAction(this);
    m_toolPadAction->setText("Spectral Plot Tool");
    m_toolPadAction->setIcon(QPixmap(toolIconDir() + "/spectral_plot.png"));
    QString text = "<b>Function:</b> Create a spectral plot using statistics across a spectrum \
                    (bands).";
    m_toolPadAction->setWhatsThis(text);
    connect(this, SIGNAL(viewportChanged()), this, SLOT(viewportSelected()));

    m_displayCombo = new QComboBox;
@@ -545,7 +548,10 @@ namespace Isis {


  /**
   *
   * This method processes the spectral plot tool's selection and creates statistics
   * for the selected pixels. For rectangular selections, a pixel is selected for statistics
   * if any part of the pixel intersects with the rectangle. For polygon selections, a pixel
   * is selected for statistics only when its center is within the polygon.
   *
   * @param labels
   * @param data
@@ -561,50 +567,54 @@ namespace Isis {
    double ss, sl, es, el, x, y;
    std::vector <int> x_contained, y_contained;

    // Convert them to line sample values
    // Convert vertices to their sub-pixel sample/line values
    viewport->viewportToCube(vertices[0].x(), vertices[0].y(), ss, sl);
    viewport->viewportToCube(vertices[2].x(), vertices[2].y(), es, el);
    
    ss = ss + 0.5;
    sl = sl + 0.5;
    es = es + 0.5;
    el = el + 0.5;
    // round the start and end sample/line sub-pixel points to the nearest int (pixel)
    ss = round(ss);
    sl = round(sl);
    es = round(es);
    el = round(el);

    int samps = (int)(es - ss + 1);
    if (samps < 1) samps = 1;
    // calculate number of samples will be in Brick's shape buffer with absolute value
    // in case user makes a rectangle from right to left
    int samps = ( (int)abs(es - ss) + 1) ;
    Cube *cube = viewport->cube();
    Brick *brick = new Brick(*cube, samps, 1, 1);
    Pvl &pvl = *viewport->cube()->label();

    if (rubberBandTool()->currentMode() == RubberBandTool::PolygonMode) {
      samps = 1;
//       samps = 1;
      geos::geom::CoordinateSequence *pts = new geos::geom::CoordinateArraySequence();
      for (int i = 0; i < vertices.size(); i++) {
        viewport->viewportToCube(vertices[i].x(), vertices[i].y(), x, y);
        pts->add(geos::geom::Coordinate((int)x, (int)y));
        // add the x,y vertices (double) to the pts CoordinateSequence
        pts->add(geos::geom::Coordinate(x, y));
      }/*end for*/

      /*Add the first point again in order to make a closed line string*/
      viewport->viewportToCube(vertices[0].x(), vertices[0].y(), x, y);
      pts->add(geos::geom::Coordinate((int)x, (int)y));
      pts->add(geos::geom::Coordinate(x, y));

      geos::geom::Polygon *poly = globalFactory.createPolygon(
          globalFactory.createLinearRing(pts), NULL);

      const geos::geom::Envelope *envelope = poly->getEnvelopeInternal();

      for (int y = (int)floor(envelope->getMinY());
           y <= (int)ceil(envelope->getMaxY());
           y++) {
        for (int x = (int)floor(envelope->getMinX());
             x <= (int)ceil(envelope->getMaxX());
             x++) {
      // round the (double) max x's and y's and min x's and y's to the nearest pixel
      for (int y = (int)round(envelope->getMinY());
           y <= (int)round(envelope->getMaxY()); y++) {
        for (int x = (int)round(envelope->getMinX()); 
             x <= (int)round(envelope->getMaxX()); x++) {
          // create a point at the center of the pixel
          geos::geom::Coordinate c(x, y);
          geos::geom::Point *p = globalFactory.createPoint(c);
          // check if the center of the pixel is in the polygon's envelope (the selection)
          bool contains = p->within(poly);
          delete p;

          if (contains) {
            // these pixels will be used for computing statistics
            x_contained.push_back(x);
            y_contained.push_back(y);
          }
@@ -623,7 +633,8 @@ namespace Isis {
      /*Rectangle*/
      if (rubberBandTool()->currentMode() == RubberBandTool::RectangleMode) {
        for (int line = (int)std::min(sl, el); line <= (int)std::max(sl, el); line++) {
          brick->SetBasePosition((int)ss, line, band);
          // set Brick's base position at left-most endpoint
          brick->SetBasePosition(std::min(ss, es), line, band);
          cube->read(*brick);
          stats.AddData(brick->DoubleBuffer(), samps);
        }
+4 −0
Original line number Diff line number Diff line
@@ -49,6 +49,10 @@ namespace Isis {
   *   @history 2014-04-03 Tracie Sucharski - Reset defaults for plots to the following:
   *                         SolidLine, Width=1, NoSymbols.  This is a temporary fix until
   *                         the defaults can be saved on a user basis.  Fixes #2062.
   *   @history 2014-07-30 Ian Humphrey - Modified getSpectralStatistics() to compute statistics
   *                           more accurately. Right-to-left selections now select pixels
   *                           correctly. Polygon selection now selects pixels more accurately
   *                           for statistics. Added What's This help. Fixes #2071. 
   */
  class SpectralPlotTool : public AbstractPlotTool {
      Q_OBJECT