private void calculateRaster() {
    amIActive = true;

    String inputHeader = null;
    String outputHeader = null;
    int col;
    int row;
    int numCols;
    int numRows;
    int a, i;
    float progress;
    int minValue, maxValue, range;
    boolean blnTextOutput = false;
    boolean zeroAsBackground = false;

    if (args.length <= 0) {
      showFeedback("Plugin parameters have not been set.");
      return;
    }

    inputHeader = args[0];
    outputHeader = args[1];
    blnTextOutput = Boolean.parseBoolean(args[2]);
    zeroAsBackground = Boolean.parseBoolean(args[3]);

    // check to see that the inputHeader and outputHeader are not null.
    if ((inputHeader == null) || (outputHeader == null)) {
      showFeedback("One or more of the input parameters have not been set properly.");
      return;
    }

    try {
      WhiteboxRaster image = new WhiteboxRaster(inputHeader, "r");

      numRows = image.getNumberRows();
      numCols = image.getNumberColumns();
      double noData = image.getNoDataValue();

      WhiteboxRaster output =
          new WhiteboxRaster(
              outputHeader, "rw", inputHeader, WhiteboxRaster.DataType.FLOAT, noData);
      output.setPreferredPalette("spectrum.pal");
      output.setDataScale(WhiteboxRaster.DataScale.CONTINUOUS);

      minValue = (int) (image.getMinimumValue());
      maxValue = (int) (image.getMaximumValue());
      range = maxValue - minValue;

      double[] data;
      // find the axis-aligned minimum bounding box.
      updateProgress("Loop 1 of 2:", 0);
      double[][] boundingBox = new double[6][range + 1];
      for (a = 0; a <= range; a++) {
        boundingBox[0][a] = Integer.MAX_VALUE; // west
        boundingBox[1][a] = Integer.MIN_VALUE; // east
        boundingBox[2][a] = Integer.MAX_VALUE; // north
        boundingBox[3][a] = Integer.MIN_VALUE; // south
      }

      for (row = 0; row < numRows; row++) {
        data = image.getRowValues(row);
        for (col = 0; col < numCols; col++) {
          if (data[col] != noData) {
            a = (int) (data[col] - minValue);
            if (col < boundingBox[0][a]) {
              boundingBox[0][a] = col;
            }
            if (col > boundingBox[1][a]) {
              boundingBox[1][a] = col;
            }
            if (row < boundingBox[2][a]) {
              boundingBox[2][a] = row;
            }
            if (row > boundingBox[3][a]) {
              boundingBox[3][a] = row;
            }
            boundingBox[5][a]++;
          }
        }
        if (cancelOp) {
          cancelOperation();
          return;
        }
        progress = (float) (100f * row / (numRows - 1));
        updateProgress("Loop 1 of 2:", (int) progress);
      }

      updateProgress("Loop 2 of 2:", 0);
      double radius;
      for (a = 0; a <= range; a++) {
        if ((boundingBox[1][a] - boundingBox[0][a] + 1)
            > (boundingBox[3][a] - boundingBox[2][a] + 1)) {
          radius = (boundingBox[1][a] - boundingBox[0][a] + 1) / 2;
        } else {
          radius = (boundingBox[3][a] - boundingBox[2][a] + 1) / 2;
        }
        boundingBox[4][a] = Math.PI * radius * radius;
      }

      if (zeroAsBackground) {
        boundingBox[0 - minValue][4] = 0d;
        // sum the column numbers and row numbers of each patch cell
        // along with the total number of cells.
        for (row = 0; row < numRows; row++) {
          data = image.getRowValues(row);
          for (col = 0; col < numCols; col++) {
            if (data[col] > 0) {
              a = (int) (data[col] - minValue);
              output.setValue(row, col, 1 - boundingBox[5][a] / boundingBox[4][a]);
            }
          }
          if (cancelOp) {
            cancelOperation();
            return;
          }
          progress = (float) (100f * row / (numRows - 1));
          updateProgress("Loop 2 of 2:", (int) progress);
        }
      } else {

        // sum the column numbers and row numbers of each patch cell
        // along with the total number of cells.
        for (row = 0; row < numRows; row++) {
          data = image.getRowValues(row);
          for (col = 0; col < numCols; col++) {
            if (data[col] != noData) {
              a = (int) (data[col] - minValue);
              output.setValue(row, col, 1 - boundingBox[5][a] / boundingBox[4][a]);
            }
          }
          if (cancelOp) {
            cancelOperation();
            return;
          }
          progress = (float) (100f * row / (numRows - 1));
          updateProgress("Loop 2 of 2:", (int) progress);
        }
      }

      output.addMetadataEntry("Created by the " + getDescriptiveName() + " tool.");
      output.addMetadataEntry("Created on " + new Date());

      image.close();
      output.close();

      if (blnTextOutput) {
        DecimalFormat df;
        df = new DecimalFormat("0.0000");

        String retstr = "Related Circumscribing Circle\nPatch ID\tValue";

        for (a = 0; a <= range; a++) {
          if (boundingBox[4][a] > 0) {
            retstr =
                retstr
                    + "\n"
                    + (a + minValue)
                    + "\t"
                    + df.format(1 - boundingBox[5][a] / boundingBox[4][a]);
          }
        }

        returnData(retstr);
      }

      // returning a header file string displays the image.
      returnData(outputHeader);

    } catch (OutOfMemoryError oe) {
      myHost.showFeedback("An out-of-memory error has occurred during operation.");
    } catch (Exception e) {
      myHost.showFeedback("An error has occurred during operation. See log file for details.");
      myHost.logException("Error in " + getDescriptiveName(), e);
    } finally {
      updateProgress("Progress: ", 0);
      // tells the main application that this process is completed.
      amIActive = false;
      myHost.pluginComplete();
    }
  }
  private void calculateDistance(WhiteboxRaster outputImage) {
    String outputHeader = outputImage.getHeaderFile();
    int row, col, whichCell, i, x, y;
    double z, z2, zMin, h = 0;
    double infVal = Float.POSITIVE_INFINITY;
    int[] dX = new int[] {-1, -1, 0, 1, 1, 1, 0, -1};
    int[] dY = new int[] {0, -1, -1, -1, 0, 1, 1, 1};
    int[] Gx = new int[] {1, 1, 0, 1, 1, 1, 0, 1};
    int[] Gy = new int[] {0, 1, 1, 1, 0, 1, 1, 1};
    int progress;

    int rows = outputImage.getNumberRows();
    int cols = outputImage.getNumberColumns();
    double noData = outputImage.getNoDataValue();
    double gridRes = (outputImage.getCellSizeX() + outputImage.getCellSizeY()) / 2;

    WhiteboxRaster Rx =
        new WhiteboxRaster(
            outputHeader.replace(".dep", "_temp1.dep"),
            "rw",
            outputHeader,
            WhiteboxRaster.DataType.FLOAT,
            0);
    Rx.isTemporaryFile = true;
    WhiteboxRaster Ry =
        new WhiteboxRaster(
            outputHeader.replace(".dep", "_temp2.dep"),
            "rw",
            outputHeader,
            WhiteboxRaster.DataType.FLOAT,
            0);
    Ry.isTemporaryFile = true;

    for (row = 0; row < rows; row++) {
      for (col = 0; col < cols; col++) {
        z = outputImage.getValue(row, col);
        if (z != 0) {
          zMin = infVal;
          whichCell = -1;
          for (i = 0; i <= 3; i++) {
            x = col + dX[i];
            y = row + dY[i];
            z2 = outputImage.getValue(y, x);
            if (z2 != noData) {
              switch (i) {
                case 0:
                  h = 2 * Rx.getValue(y, x) + 1;
                  break;
                case 1:
                  h = 2 * (Rx.getValue(y, x) + Ry.getValue(y, x) + 1);
                  break;
                case 2:
                  h = 2 * Ry.getValue(y, x) + 1;
                  break;
                case 3:
                  h = 2 * (Rx.getValue(y, x) + Ry.getValue(y, x) + 1);
                  break;
              }
              z2 += h;
              if (z2 < zMin) {
                zMin = z2;
                whichCell = i;
              }
            }
          }
          if (zMin < z) {
            outputImage.setValue(row, col, zMin);
            x = col + dX[whichCell];
            y = row + dY[whichCell];
            Rx.setValue(row, col, Rx.getValue(y, x) + Gx[whichCell]);
            Ry.setValue(row, col, Ry.getValue(y, x) + Gy[whichCell]);
          }
        }
      }
      if (cancelOp) {
        cancelOperation();
        return;
      }
      progress = (int) (100f * row / (rows - 1));
      updateProgress("Calculating distances: ", progress);
    }

    for (row = rows - 1; row >= 0; row--) {
      for (col = cols - 1; col >= 0; col--) {
        z = outputImage.getValue(row, col);
        if (z != 0) {
          zMin = infVal;
          whichCell = -1;
          for (i = 4; i <= 7; i++) {
            x = col + dX[i];
            y = row + dY[i];
            z2 = outputImage.getValue(y, x);
            if (z2 != noData) {
              switch (i) {
                case 5:
                  h = 2 * (Rx.getValue(y, x) + Ry.getValue(y, x) + 1);
                  break;
                case 4:
                  h = 2 * Rx.getValue(y, x) + 1;
                  break;
                case 6:
                  h = 2 * Ry.getValue(y, x) + 1;
                  break;
                case 7:
                  h = 2 * (Rx.getValue(y, x) + Ry.getValue(y, x) + 1);
                  break;
              }
              z2 += h;
              if (z2 < zMin) {
                zMin = z2;
                whichCell = i;
              }
            }
          }
          if (zMin < z) {
            outputImage.setValue(row, col, zMin);
            x = col + dX[whichCell];
            y = row + dY[whichCell];
            Rx.setValue(row, col, Rx.getValue(y, x) + Gx[whichCell]);
            Ry.setValue(row, col, Ry.getValue(y, x) + Gy[whichCell]);
          }
        }
      }
      if (cancelOp) {
        cancelOperation();
        return;
      }
      progress = (int) (100f * (rows - 1 - row) / (rows - 1));
      updateProgress("Calculating distances: ", progress);
    }

    //        for (row = 0; row < rows; row++) {
    //            for (col = 0; col < cols; col++) {
    //                z = outputImage.getValue(row, col);
    //                outputImage.setValue(row, col, Math.sqrt(z) * gridRes);
    //            }
    //            if (cancelOp) {
    //                cancelOperation();
    //                return;
    //            }
    //            progress = (int) (100f * row / (rows - 1));
    //            updateProgress(progress);
    //        }

    outputImage.flush();
    Rx.close();
    Ry.close();
  }
  private void histogramMatching(String inputHeader1, String inputHeader2, String outputHeader) {

    // check to see that the inputHeader and outputHeader are not null.
    if (inputHeader1.isEmpty() || outputHeader.isEmpty() || inputHeader2.isEmpty()) {
      showFeedback("One or more of the input parameters have not been set properly.");
      return;
    }

    try {
      int row, col;
      double z;
      int progress = 0;
      int numCells1 = 0;
      int numCells2 = 0;
      int i = 0;

      WhiteboxRasterInfo inputFile1 = new WhiteboxRasterInfo(inputHeader1);
      int rows1 = inputFile1.getNumberRows();
      int cols1 = inputFile1.getNumberColumns();
      double noData1 = inputFile1.getNoDataValue();

      WhiteboxRasterInfo inputFile2 = new WhiteboxRasterInfo(inputHeader2);
      int rows2 = inputFile2.getNumberRows();
      int cols2 = inputFile2.getNumberColumns();
      double noData2 = inputFile2.getNoDataValue();

      WhiteboxRaster outputFile =
          new WhiteboxRaster(
              outputHeader, "rw", inputHeader1, WhiteboxRaster.DataType.FLOAT, noData1);
      outputFile.setPreferredPalette(inputFile1.getPreferredPalette());

      double minValue1 = inputFile1.getMinimumValue();
      double maxValue1 = inputFile1.getMaximumValue();
      int numBins1 =
          Math.max(
              2 * (int) Math.ceil(maxValue1 - minValue1 + 1),
              (int) Math.ceil(Math.pow(rows1 * cols1, 1.0 / 3)));
      double binSize = (maxValue1 - minValue1) / numBins1;
      long[] histogram = new long[numBins1];
      int binNum;
      int numBinsLessOne1 = numBins1 - 1;
      double[] data;

      updateProgress("Histogram matching: ", 0);
      for (row = 0; row < rows1; row++) {
        data = inputFile1.getRowValues(row);
        for (col = 0; col < cols1; col++) {
          z = data[col];
          if (z != noData1) {
            numCells1++;
            binNum = (int) ((z - minValue1) / binSize);
            if (binNum > numBinsLessOne1) {
              binNum = numBinsLessOne1;
            }
            histogram[binNum]++;
          }
        }
        if (cancelOp) {
          cancelOperation();
          return;
        }
        progress = (int) (100f * row / (rows1 - 1));
        updateProgress("Histogram matching: ", progress);
      }

      updateProgress("Histogram matching: ", 0);

      double[] cdf = new double[numBins1];
      cdf[0] = histogram[0];
      for (i = 1; i < numBins1; i++) {
        cdf[i] = cdf[i - 1] + histogram[i];
      }

      for (i = 0; i < numBins1; i++) {
        cdf[i] = cdf[i] / numCells1;
      }

      double minValue2 = inputFile2.getMinimumValue();
      double maxValue2 = inputFile2.getMaximumValue();

      int numBins2 =
          Math.max(
              2 * (int) Math.ceil(maxValue2 - minValue2 + 1),
              (int) Math.ceil(Math.pow(rows2 * cols2, 1.0 / 3)));
      int numBinsLessOne2 = numBins2 - 1;
      long[] histogram2 = new long[numBins2];
      double[][] referenceCDF = new double[numBins2][2];

      for (row = 0; row < rows2; row++) {
        data = inputFile2.getRowValues(row);
        for (col = 0; col < cols2; col++) {
          z = data[col];
          if (z != noData2) {
            numCells2++;
            binNum = (int) ((z - minValue2) / binSize);
            if (binNum > numBinsLessOne2) {
              binNum = numBinsLessOne2;
            }
            histogram2[binNum]++;
          }
        }
        if (cancelOp) {
          cancelOperation();
          return;
        }
        progress = (int) (100f * row / (rows1 - 1));
        updateProgress("Histogram matching: ", progress);
      }

      // convert the reference histogram to a cdf.
      referenceCDF[0][1] = histogram2[0];
      for (i = 1; i < numBins2; i++) {
        referenceCDF[i][1] = referenceCDF[i - 1][1] + histogram2[i];
      }

      for (i = 0; i < numBins2; i++) {
        referenceCDF[i][0] = minValue2 + (i / (float) numBins2) * (maxValue2 - minValue2);
        referenceCDF[i][1] = referenceCDF[i][1] / numCells2;
      }

      int[] startingVals = new int[11];
      double pVal = 0;
      for (i = 0; i < numBins2; i++) {
        pVal = referenceCDF[i][1];
        if (pVal < 0.1) {
          startingVals[1] = i;
        }
        if (pVal < 0.2) {
          startingVals[2] = i;
        }
        if (pVal < 0.3) {
          startingVals[3] = i;
        }
        if (pVal < 0.4) {
          startingVals[4] = i;
        }
        if (pVal < 0.5) {
          startingVals[5] = i;
        }
        if (pVal < 0.6) {
          startingVals[6] = i;
        }
        if (pVal < 0.7) {
          startingVals[7] = i;
        }
        if (pVal < 0.8) {
          startingVals[8] = i;
        }
        if (pVal < 0.9) {
          startingVals[9] = i;
        }
        if (pVal <= 1) {
          startingVals[10] = i;
        }
      }

      updateProgress("Histogram matching: ", 0);
      int j = 0;
      double xVal = 0;
      double x1, x2, p1, p2;
      for (row = 0; row < rows1; row++) {
        data = inputFile1.getRowValues(row);
        for (col = 0; col < cols1; col++) {
          z = data[col];
          if (z != noData1) {
            binNum = (int) ((z - minValue1) / binSize);
            if (binNum > numBinsLessOne1) {
              binNum = numBinsLessOne1;
            }
            pVal = cdf[binNum];
            j = (int) (Math.floor(pVal * 10));
            for (i = startingVals[j]; i < numBins2; i++) {
              if (referenceCDF[i][1] > pVal) {
                if (i > 0) {
                  x1 = referenceCDF[i - 1][0];
                  x2 = referenceCDF[i][0];
                  p1 = referenceCDF[i - 1][1];
                  p2 = referenceCDF[i][1];
                  if (p1 != p2) {
                    xVal = x1 + ((x2 - x1) * ((pVal - p1) / (p2 - p1)));
                  } else {
                    xVal = x1;
                  }
                } else {
                  xVal = referenceCDF[i][0];
                }
                break;
              }
            }

            outputFile.setValue(row, col, xVal);
          }
        }

        if (cancelOp) {
          cancelOperation();
          return;
        }
        progress = (int) (100f * row / (rows1 - 1));
        updateProgress("Histogram matching: ", progress);
      }

      inputFile1.close();
      outputFile.close();

    } catch (OutOfMemoryError oe) {
      myHost.showFeedback("An out-of-memory error has occurred during operation.");
    } catch (Exception e) {
      myHost.showFeedback("An error has occurred during operation. See log file for details.");
      myHost.logException("Error in " + getDescriptiveName(), e);
    } finally {
      updateProgress("Progress: ", 0);
    }
  }
  @Override
  public void run() {
    amIActive = true;

    int progress;
    int row, col, i;
    int baseCol, baseRow, appendCol, appendRow;
    double x, y, z, zN, zBase, zAppend;
    double w1, w2, dist1, dist2, sumDist;
    boolean performHistoMatching = true;

    if (args.length <= 0) {
      showFeedback("Plugin parameters have not been set.");
      return;
    }

    // read the input parameters
    String inputBaseHeader = args[0];
    String inputHeader = args[1];
    String outputHeader = args[2];
    String resampleMethod = args[3].toLowerCase().trim();
    if (!resampleMethod.equals("nearest neighbour")
        && !resampleMethod.equals("bilinear")
        && !resampleMethod.contains("cubic")) {
      showFeedback("Resample method not recognized");
      return;
    }
    if (args[4].toLowerCase().contains("true")) {
      performHistoMatching = true;
    } else {
      performHistoMatching = false;
    }
    double power = Double.parseDouble(args[5]);
    if (power > 15.0) {
      power = 15.0;
    }
    if (power < 1.0) {
      power = 1.0;
    }

    try {

      // first perform histogram matching if necessary
      if (performHistoMatching) {
        String inputHeaderAdjusted = StringUtilities.replaceLast(inputHeader, ".dep", "_temp1.dep");
        histogramMatching(inputHeader, inputBaseHeader, inputHeaderAdjusted);
        inputHeader = inputHeaderAdjusted;
      }

      WhiteboxRaster baseRaster = new WhiteboxRaster(inputBaseHeader, "r");
      WhiteboxRaster appendRaster = new WhiteboxRaster(inputHeader, "r");

      double cellSizeX = baseRaster.getCellSizeX();
      double cellSizeY = baseRaster.getCellSizeY();
      double baseNoData = baseRaster.getNoDataValue();
      double appendNoData = appendRaster.getNoDataValue();
      double outputNoData = baseNoData;
      int baseCols = baseRaster.getNumberColumns();
      int baseRows = baseRaster.getNumberRows();
      int appendCols = appendRaster.getNumberColumns();
      int appendRows = appendRaster.getNumberRows();

      // figure out the north, south, east, and west coordinates and the rows and
      // columns of the output image.
      double baseNorth = baseRaster.getNorth();
      double baseSouth = baseRaster.getSouth();
      double baseEast = baseRaster.getEast();
      double baseWest = baseRaster.getWest();
      double baseNSRange = baseNorth - baseSouth;
      double baseEWRange = baseEast - baseWest;

      double appendNorth = appendRaster.getNorth();
      double appendSouth = appendRaster.getSouth();
      double appendEast = appendRaster.getEast();
      double appendWest = appendRaster.getWest();
      double appendNSRange = appendNorth - appendSouth;
      double appendEWRange = appendEast - appendWest;

      double north, south, east, west;

      if (baseNorth > baseSouth) {
        north = Double.NEGATIVE_INFINITY;
        south = Double.POSITIVE_INFINITY;

        if (baseNorth > north) {
          north = baseNorth;
        }
        if (appendNorth > north) {
          north = appendNorth;
        }
        if (baseSouth < south) {
          south = baseSouth;
        }
        if (appendSouth < south) {
          south = appendSouth;
        }
      } else {
        north = Double.POSITIVE_INFINITY;
        south = Double.NEGATIVE_INFINITY;

        if (baseNorth < north) {
          north = baseNorth;
        }
        if (appendNorth < north) {
          north = appendNorth;
        }
        if (baseSouth > south) {
          south = baseSouth;
        }
        if (appendSouth > south) {
          south = appendSouth;
        }
      }
      if (baseEast > baseWest) {
        east = Double.NEGATIVE_INFINITY;
        west = Double.POSITIVE_INFINITY;

        if (baseEast > east) {
          east = baseEast;
        }
        if (appendEast > east) {
          east = appendEast;
        }
        if (baseWest < west) {
          west = baseWest;
        }
        if (appendWest < west) {
          west = appendWest;
        }
      } else {
        east = Double.POSITIVE_INFINITY;
        west = Double.NEGATIVE_INFINITY;

        if (baseEast < east) {
          east = baseEast;
        }
        if (appendEast < east) {
          east = appendEast;
        }
        if (baseWest > west) {
          west = baseWest;
        }
        if (appendWest > west) {
          west = appendWest;
        }
      }

      // create the new destination image.
      int nRows = (int) Math.round(Math.abs(north - south) / cellSizeY);
      int nCols = (int) Math.round(Math.abs(east - west) / cellSizeX);

      WhiteboxRaster destination =
          new WhiteboxRaster(
              outputHeader,
              north,
              south,
              east,
              west,
              nRows,
              nCols,
              WhiteboxRasterBase.DataScale.CONTINUOUS,
              WhiteboxRasterBase.DataType.FLOAT,
              outputNoData,
              outputNoData);

      int nRowsLessOne = nRows - 1;

      // distance to edge images
      String distToEdgeBaseHeader =
          StringUtilities.replaceLast(inputBaseHeader, ".dep", "_temp1.dep");
      WhiteboxRaster distToEdgeBase =
          new WhiteboxRaster(
              distToEdgeBaseHeader,
              "rw",
              inputBaseHeader,
              WhiteboxRaster.DataType.FLOAT,
              Float.POSITIVE_INFINITY);
      distToEdgeBase.isTemporaryFile = true;

      double[] data;
      for (row = 0; row < baseRows; row++) {
        data = baseRaster.getRowValues(row);
        for (col = 0; col < baseCols; col++) {
          if (row == 0 || row == baseRows - 1) {
            distToEdgeBase.setValue(row, col, 0.0);
          } else if (col == 0 || col == baseCols - 1) {
            distToEdgeBase.setValue(row, col, 0.0);
          } else {
            if (data[col] != baseNoData) {
              if (data[col - 1] == baseNoData || data[col + 1] == baseNoData) {
                distToEdgeBase.setValue(row, col, 0.0);
              }
            } else {
              distToEdgeBase.setValue(row, col, 0.0);
            }
          }
        }
      }

      calculateDistance(distToEdgeBase);

      String distToEdgeAppendHeader =
          whitebox.utilities.StringUtilities.replaceLast(inputBaseHeader, ".dep", "_temp2.dep");
      WhiteboxRaster distToEdgeAppend =
          new WhiteboxRaster(
              distToEdgeAppendHeader,
              "rw",
              inputHeader,
              WhiteboxRaster.DataType.FLOAT,
              Float.POSITIVE_INFINITY);
      distToEdgeAppend.isTemporaryFile = true;

      for (row = 0; row < appendRows; row++) {
        data = appendRaster.getRowValues(row);
        for (col = 0; col < appendCols; col++) {
          if (row == 0 || row == appendRows - 1) {
            distToEdgeAppend.setValue(row, col, 0.0);
          } else if (col == 0 || col == appendCols - 1) {
            distToEdgeAppend.setValue(row, col, 0.0);
          } else {
            if (data[col] != appendNoData) {
              if (data[col - 1] == appendNoData || data[col + 1] == appendNoData) {
                distToEdgeAppend.setValue(row, col, 0.0);
              }
            } else {
              distToEdgeAppend.setValue(row, col, 0.0);
            }
          }
        }
      }

      calculateDistance(distToEdgeAppend);

      if (resampleMethod.contains("nearest")) {
        for (row = 0; row < nRows; row++) {
          for (col = 0; col < nCols; col++) {
            x = destination.getXCoordinateFromColumn(col);
            y = destination.getYCoordinateFromRow(row);

            baseCol = baseRaster.getColumnFromXCoordinate(x);
            baseRow = baseRaster.getRowFromYCoordinate(y);

            appendCol = appendRaster.getColumnFromXCoordinate(x);
            appendRow = appendRaster.getRowFromYCoordinate(y);

            zBase = baseRaster.getValue(baseRow, baseCol);
            zAppend = appendRaster.getValue(appendRow, appendCol);

            if (zBase != baseNoData && zAppend == appendNoData) {
              destination.setValue(row, col, zBase);
            } else if (zBase == baseNoData && zAppend != appendNoData) {
              destination.setValue(row, col, zAppend);
            } else if (zBase == baseNoData && zAppend == appendNoData) {
              destination.setValue(row, col, outputNoData);
            } else { // two valid values.

              // find the distance to the nearest edge in the base image
              dist1 = distToEdgeBase.getValue(baseRow, baseCol); // baseCol;
              dist2 = distToEdgeAppend.getValue(appendRow, appendCol); // appendCol;

              sumDist = Math.pow(dist1, power) + Math.pow(dist2, power);

              w1 = Math.pow(dist1, power) / sumDist;
              w2 = Math.pow(dist2, power) / sumDist;

              z = w1 * zBase + w2 * zAppend;

              destination.setValue(row, col, z);
            }
          }
          if (cancelOp) {
            cancelOperation();
            return;
          }
          progress = (int) (100f * row / nRowsLessOne);
          updateProgress("Resampling images: ", progress);
        }
      } else {
        if (destination.getDataType() != WhiteboxRaster.DataType.DOUBLE
            && destination.getDataType() != WhiteboxRaster.DataType.FLOAT) {
          showFeedback(
              "The destination image is not of an appropriate data"
                  + " type (i.e. double or float) to perform this operation.");
          return;
        }
        double dX, dY;
        double srcRow, srcCol;
        double originRow, originCol;
        double rowN, colN;
        double sumOfDist;
        double[] shiftX;
        double[] shiftY;
        int numNeighbours = 0;
        double[][] neighbour;
        if (resampleMethod.contains("cubic")) {
          shiftX = new double[] {-1, 0, 1, 2, -1, 0, 1, 2, -1, 0, 1, 2, -1, 0, 1, 2};
          shiftY = new double[] {-1, -1, -1, -1, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2};
          numNeighbours = 16;
          neighbour = new double[numNeighbours][2];
        } else { // resampleMethod is "bilinear"
          shiftX = new double[] {0, 1, 0, 1};
          shiftY = new double[] {0, 0, 1, 1};
          numNeighbours = 4;
          neighbour = new double[numNeighbours][2];
        }

        for (row = 0; row < nRows; row++) {
          for (col = 0; col < nCols; col++) {
            x = destination.getXCoordinateFromColumn(col);
            y = destination.getYCoordinateFromRow(row);

            baseCol = baseRaster.getColumnFromXCoordinate(x);
            baseRow = baseRaster.getRowFromYCoordinate(y);

            // what are the exact col and row of the image?
            srcRow = (baseNorth - y) / baseNSRange * (baseRows - 0.5);
            srcCol = (x - baseWest) / baseEWRange * (baseCols - 0.5);

            originRow = Math.floor(srcRow);
            originCol = Math.floor(srcCol);

            sumOfDist = 0;
            for (i = 0; i < numNeighbours; i++) {
              rowN = originRow + shiftY[i];
              colN = originCol + shiftX[i];
              neighbour[i][0] = baseRaster.getValue((int) rowN, (int) colN);
              dY = rowN - srcRow;
              dX = colN - srcCol;

              if ((dX + dY) != 0 && neighbour[i][0] != baseNoData) {
                neighbour[i][1] = 1 / (dX * dX + dY * dY);
                sumOfDist += neighbour[i][1];
              } else if (neighbour[i][0] == baseNoData) {
                neighbour[i][1] = 0;
              } else { // dist is zero
                neighbour[i][1] = 99999999;
                sumOfDist += neighbour[i][1];
              }
            }

            if (sumOfDist > 0) {
              z = 0;
              for (i = 0; i < numNeighbours; i++) {
                z += neighbour[i][0] * neighbour[i][1] / sumOfDist;
              }
              zBase = z;
            } else {
              zBase = baseNoData;
            }

            appendCol = appendRaster.getColumnFromXCoordinate(x);
            appendRow = appendRaster.getRowFromYCoordinate(y);

            srcRow = (appendNorth - y) / appendNSRange * (appendRows - 0.5);
            srcCol = (x - appendWest) / appendEWRange * (appendCols - 0.5);

            originRow = Math.floor(srcRow);
            originCol = Math.floor(srcCol);

            sumOfDist = 0;
            for (i = 0; i < numNeighbours; i++) {
              rowN = originRow + shiftY[i];
              colN = originCol + shiftX[i];
              neighbour[i][0] = appendRaster.getValue((int) rowN, (int) colN);
              dY = rowN - srcRow;
              dX = colN - srcCol;

              if ((dX + dY) != 0 && neighbour[i][0] != appendNoData) {
                neighbour[i][1] = 1 / (dX * dX + dY * dY);
                sumOfDist += neighbour[i][1];
              } else if (neighbour[i][0] == appendNoData) {
                neighbour[i][1] = 0;
              } else { // dist is zero
                neighbour[i][1] = 99999999;
                sumOfDist += neighbour[i][1];
              }
            }

            if (sumOfDist > 0) {
              z = 0;
              for (i = 0; i < numNeighbours; i++) {
                z += (neighbour[i][0] * neighbour[i][1]) / sumOfDist;
              }
              zAppend = z;
            } else {
              zAppend = appendNoData;
            }

            if (zBase != baseNoData && zAppend == appendNoData) {
              destination.setValue(row, col, zBase);
            } else if (zBase == baseNoData && zAppend != appendNoData) {
              destination.setValue(row, col, zAppend);
            } else if (zBase == baseNoData && zAppend == appendNoData) {
              destination.setValue(row, col, outputNoData);
            } else { // two valid values.

              // find the distance to the nearest edge in the base image
              dist1 = distToEdgeBase.getValue(baseRow, baseCol); // baseCol;
              dist2 = distToEdgeAppend.getValue(appendRow, appendCol); // appendCol;

              sumDist = dist1 + dist2;

              w1 = dist1 / sumDist;
              w2 = dist2 / sumDist;

              z = w1 * zBase + w2 * zAppend;

              destination.setValue(row, col, z);
            }
          }
          if (cancelOp) {
            cancelOperation();
            return;
          }
          progress = (int) (100f * row / nRowsLessOne);
          updateProgress("Resampling images: ", progress);
        }
      }

      destination.addMetadataEntry("Created by the " + getDescriptiveName() + " tool.");
      destination.addMetadataEntry("Created on " + new Date());

      destination.close();
      distToEdgeBase.close();
      distToEdgeAppend.close();
      baseRaster.close();

      if (performHistoMatching) {
        File header = new File(inputHeader);
        if (header.exists()) {
          header.delete();
        }
        File dataFile = new File(StringUtilities.replaceLast(inputHeader, ".dep", ".tas"));
        if (dataFile.exists()) {
          dataFile.delete();
        }
      } else {
        appendRaster.close();
      }

      returnData(outputHeader);

    } catch (OutOfMemoryError oe) {
      myHost.showFeedback("An out-of-memory error has occurred during operation.");
    } catch (Exception e) {
      myHost.showFeedback("An error has occurred during operation. See log file for details.");
      myHost.logException("Error in " + getDescriptiveName(), e);
    } finally {
      updateProgress("Progress: ", 0);
      // tells the main application that this process is completed.
      amIActive = false;
      myHost.pluginComplete();
    }
  }
コード例 #5
0
  /** Used to execute this plugin tool. */
  @Override
  public void run() {
    /*
     * This transformation has been taken from:
     * http://ij.ms3d.de/pdf/ihs_transforms.pdf
     * in reference to Haydn, Dalke, and Henkel (1982)
     * Note: 0 <= I <= 3, 0 <= H <= 3, 0 <= S <= 1
     */

    amIActive = true;

    String redHeader, greenHeader, blueHeader, intensityHeader, saturationHeader, hueHeader;

    if (args.length <= 0) {
      showFeedback("Plugin parameters have not been set.");
      return;
    }

    redHeader = args[0];
    greenHeader = args[1];
    blueHeader = args[2];
    intensityHeader = args[3];
    hueHeader = args[4];
    saturationHeader = args[5];

    // check to see that the inputHeader and outputHeader are not null.
    if (redHeader.isEmpty()
        || greenHeader.isEmpty()
        || blueHeader == null
        || intensityHeader.isEmpty()
        || hueHeader.isEmpty()
        || saturationHeader.isEmpty()) {
      showFeedback("One or more of the input parameters have not been set properly.");
      return;
    }

    try {
      int row, col;
      double redVal, greenVal, blueVal;
      //            double redRange, greenRange, blueRange;
      //            double redMin, greenMin, blueMin;
      double r, g, b;
      double i, s, h, m;
      float progress;

      WhiteboxRasterInfo red = new WhiteboxRasterInfo(redHeader);

      int rows = red.getNumberRows();
      int cols = red.getNumberColumns();

      WhiteboxRasterInfo green = new WhiteboxRasterInfo(greenHeader);
      if (green.getNumberRows() != rows || green.getNumberColumns() != cols) {
        showFeedback("All input images must have the same dimensions.");
        return;
      }
      WhiteboxRasterInfo blue = new WhiteboxRasterInfo(blueHeader);
      if (blue.getNumberRows() != rows || blue.getNumberColumns() != cols) {
        showFeedback("All input images must have the same dimensions.");
        return;
      }

      double redNoData = red.getNoDataValue();
      double greenNoData = green.getNoDataValue();
      double blueNoData = blue.getNoDataValue();

      WhiteboxRaster intensity =
          new WhiteboxRaster(
              intensityHeader, "rw", redHeader, WhiteboxRaster.DataType.FLOAT, redNoData);

      WhiteboxRaster hue =
          new WhiteboxRaster(hueHeader, "rw", redHeader, WhiteboxRaster.DataType.FLOAT, redNoData);

      WhiteboxRaster saturation =
          new WhiteboxRaster(
              saturationHeader, "rw", redHeader, WhiteboxRaster.DataType.FLOAT, redNoData);

      //            redMin = red.getDisplayMinimum();
      //            greenMin = green.getDisplayMinimum();
      //            blueMin = blue.getDisplayMinimum();
      //
      //            redRange = red.getDisplayMaximum() - redMin;
      //            greenRange = green.getDisplayMaximum() - greenMin;
      //            blueRange = blue.getDisplayMaximum() - blueMin;

      double overallMin =
          Math.min(
              Math.min(red.getDisplayMinimum(), green.getDisplayMinimum()),
              blue.getDisplayMinimum());

      double overallMax =
          Math.max(
              Math.max(red.getDisplayMaximum(), green.getDisplayMaximum()),
              blue.getDisplayMaximum());

      double range = overallMax - overallMin;

      double[] dataRed, dataGreen, dataBlue;
      for (row = 0; row < rows; row++) {
        dataRed = red.getRowValues(row);
        dataGreen = green.getRowValues(row);
        dataBlue = blue.getRowValues(row);
        for (col = 0; col < cols; col++) {
          redVal = dataRed[col];
          greenVal = dataGreen[col];
          blueVal = dataBlue[col];
          if ((redVal != redNoData) && (greenVal != greenNoData) && (blueVal != blueNoData)) {
            r = (redVal - overallMin) / range;
            if (r < 0) {
              r = 0;
            }
            if (r > 1) {
              r = 1;
            }
            g = (greenVal - overallMin) / range;
            if (g < 0) {
              g = 0;
            }
            if (g > 1) {
              g = 1;
            }
            b = (blueVal - overallMin) / range;
            if (b < 0) {
              b = 0;
            }
            if (b > 1) {
              b = 1;
            }

            m = Math.min(Math.min(r, g), b);

            i = r + g + b;

            if (i == 3) {
              h = 0;
            } else if (m == b) {
              h = (g - b) / (i - 3 * b);
            } else if (m == r) {
              h = (b - r) / (i - 3 * r) + 1;
            } else { // m == g
              h = (r - g) / (i - 3 * g) + 2;
            }

            if (h <= 1) {
              s = (i - 3 * b) / i;
            } else if (h <= 2) {
              s = (i - 3 * r) / i;
            } else { // H <= 3
              s = (i - 3 * g) / i;
            }

            intensity.setValue(row, col, i);
            hue.setValue(row, col, h);
            saturation.setValue(row, col, s);
          } else {
            intensity.setValue(row, col, redNoData);
            hue.setValue(row, col, redNoData);
            saturation.setValue(row, col, redNoData);
          }
        }
        if (cancelOp) {
          cancelOperation();
          return;
        }
        progress = (float) (100f * row / (rows - 1));
        updateProgress((int) progress);
      }

      intensity.addMetadataEntry("Created by the " + getDescriptiveName() + " tool.");
      intensity.addMetadataEntry("Created on " + new Date());
      intensity.close();

      hue.addMetadataEntry("Created by the " + getDescriptiveName() + " tool.");
      hue.addMetadataEntry("Created on " + new Date());
      hue.close();

      saturation.addMetadataEntry("Created by the " + getDescriptiveName() + " tool.");
      saturation.addMetadataEntry("Created on " + new Date());
      saturation.close();

      red.close();
      green.close();
      blue.close();

      // returning a header file string displays the image.
      returnData(intensityHeader);
      returnData(hueHeader);
      returnData(saturationHeader);

    } catch (OutOfMemoryError oe) {
      myHost.showFeedback("An out-of-memory error has occurred during operation.");
    } catch (Exception e) {
      myHost.showFeedback("An error has occurred during operation. See log file for details.");
      myHost.logException("Error in " + getDescriptiveName(), e);
    } finally {
      updateProgress("Progress: ", 0);
      // tells the main application that this process is completed.
      amIActive = false;
      myHost.pluginComplete();
    }
  }
  /** Used to execute this plugin tool. */
  @Override
  public void run() {
    amIActive = true;

    String streamsHeader;
    String pointerHeader;
    String outputFileName;
    int row, col, x, y;
    double xCoord, yCoord;
    int progress;
    int c;
    int[] dX = new int[] {1, 1, 1, 0, -1, -1, -1, 0};
    int[] dY = new int[] {-1, 0, 1, 1, 1, 0, -1, -1};
    double[] inflowingVals = new double[] {16, 32, 64, 128, 1, 2, 4, 8};
    boolean flag;
    double flowDir;
    double previousFlowDir;
    double linkLength;
    double streamValue;

    if (args.length <= 0) {
      showFeedback("Plugin parameters have not been set.");
      return;
    }

    streamsHeader = args[0];
    pointerHeader = args[1];
    outputFileName = args[2];

    // check to see that the inputHeader and outputHeader are not null.
    if ((streamsHeader == null) || (pointerHeader == null) || (outputFileName == null)) {
      showFeedback("One or more of the input parameters have not been set properly.");
      return;
    }

    try {
      WhiteboxRaster streams = new WhiteboxRaster(streamsHeader, "r");
      int rows = streams.getNumberRows();
      int cols = streams.getNumberColumns();
      double noData = streams.getNoDataValue();
      double gridResX = streams.getCellSizeX();
      double gridResY = streams.getCellSizeY();
      double diagGridRes = Math.sqrt(gridResX * gridResX + gridResY * gridResY);
      double[] gridLengths =
          new double[] {
            diagGridRes,
            gridResX,
            diagGridRes,
            gridResY,
            diagGridRes,
            gridResX,
            diagGridRes,
            gridResY
          };
      double east = streams.getEast() - gridResX / 2.0;
      double west = streams.getWest() + gridResX / 2.0;
      double EWRange = east - west;
      double north = streams.getNorth() - gridResY / 2.0;
      double south = streams.getSouth() + gridResY / 2.0;
      double NSRange = north - south;

      WhiteboxRaster pntr = new WhiteboxRaster(pointerHeader, "r");

      if (pntr.getNumberRows() != rows || pntr.getNumberColumns() != cols) {
        showFeedback("The input images must be of the same dimensions.");
        return;
      }

      DBFField fields[] = new DBFField[3];

      fields[0] = new DBFField();
      fields[0].setName("FID");
      fields[0].setDataType(DBFField.DBFDataType.NUMERIC);
      fields[0].setFieldLength(10);
      fields[0].setDecimalCount(0);

      fields[1] = new DBFField();
      fields[1].setName("STRM_VAL");
      fields[1].setDataType(DBFField.DBFDataType.NUMERIC);
      fields[1].setFieldLength(10);
      fields[1].setDecimalCount(3);

      fields[2] = new DBFField();
      fields[2].setName("Length");
      fields[2].setDataType(DBFField.DBFDataType.NUMERIC);
      fields[2].setFieldLength(10);
      fields[2].setDecimalCount(3);

      // set up the output files of the shapefile and the dbf
      ShapeFile output = new ShapeFile(outputFileName, ShapeType.POLYLINE, fields);

      byte numNeighbouringStreamCells;
      int FID = 0;
      for (row = 0; row < rows; row++) {
        for (col = 0; col < cols; col++) {
          streamValue = streams.getValue(row, col);
          if (streamValue > 0) {
            // see if it is a headwater location
            numNeighbouringStreamCells = 0;
            for (c = 0; c < 8; c++) {
              x = col + dX[c];
              y = row + dY[c];
              if (streams.getValue(y, x) > 0 && pntr.getValue(y, x) == inflowingVals[c]) {
                numNeighbouringStreamCells++;
              }
            }
            if (numNeighbouringStreamCells != 1) {
              // it's the start of a link.
              FID++;
              linkLength = 0;
              int[] parts = {0};
              PointsList points = new PointsList();
              x = col;
              y = row;
              previousFlowDir = -99;
              flag = true;
              do {
                // find the downslope neighbour
                flowDir = pntr.getValue(y, x);
                if (flowDir > 0) {
                  if (flowDir != previousFlowDir) {
                    // it's a bend in the stream so add this point
                    xCoord = west + ((double) x / cols) * EWRange;
                    yCoord = north - ((double) y / rows) * NSRange;
                    points.addPoint(xCoord, yCoord);

                    previousFlowDir = flowDir;
                  }

                  // update the row and column values to the
                  // cell that the flowpath leads to.
                  c = (int) (Math.log(flowDir) / LnOf2);
                  if (c > 7) {
                    showFeedback(
                        "An unexpected value has "
                            + "been identified in the pointer "
                            + "image. This tool requires a "
                            + "pointer grid that has been "
                            + "created using either the D8 "
                            + "or Rho8 tools.");
                    return;
                  }

                  x += dX[c];
                  y += dY[c];

                  linkLength += gridLengths[c];

                  if (streams.getValue(y, x) <= 0) { // it's not a stream cell
                    flag = false;
                  } else {
                    // is it a confluence
                    numNeighbouringStreamCells = 0;
                    int x2, y2;
                    for (int d = 0; d < 8; d++) {
                      x2 = x + dX[d];
                      y2 = y + dY[d];
                      if (streams.getValue(y2, x2) > 0
                          && pntr.getValue(y2, x2) == inflowingVals[d]) {
                        numNeighbouringStreamCells++;
                      }
                    }
                    if (numNeighbouringStreamCells > 1) {
                      // It's a confluence and you should stop here.
                      flag = false;
                    }
                  }

                } else {
                  flag = false;
                }

                if (!flag) {
                  // it's the end of the stream link so
                  // add the point.
                  xCoord = west + ((double) x / cols) * EWRange;
                  yCoord = north - ((double) y / rows) * NSRange;
                  points.addPoint(xCoord, yCoord);
                }

              } while (flag);

              // add the line to the shapefile.
              PolyLine line = new PolyLine(parts, points.getPointsArray());
              Object[] rowData = new Object[3];
              rowData[0] = new Double(FID);
              rowData[1] = new Double(streamValue);
              rowData[2] = new Double(linkLength / 1000.0);
              output.addRecord(line, rowData);
            }
          }
        }
        if (cancelOp) {
          cancelOperation();
          return;
        }
        progress = (int) (100f * row / (rows - 1));
        updateProgress(progress);
      }
      output.write();

      pntr.close();
      streams.close();

      // returning a header file string displays the image.
      returnData(outputFileName);

    } catch (OutOfMemoryError oe) {
      myHost.showFeedback("An out-of-memory error has occurred during operation.");
    } catch (Exception e) {
      myHost.showFeedback("An error has occurred during operation. See log file for details.");
      myHost.logException("Error in " + getDescriptiveName(), e);
    } finally {
      updateProgress("Progress: ", 0);
      // tells the main application that this process is completed.
      amIActive = false;
      myHost.pluginComplete();
    }
  }