Program: 140969
Project: 140969
Buggy source:
/** 
 * Line integral convolution of normal vectors with uniform sampling distance and Gaussian weights along a line of steepest slope in uphill and downhill direction.
 * @param grid scalar field
 * @param row start position row
 * @param col start position column
 */
private void lic(SlopeLineIterator iter,Grid src,int row,int col){
  double cellSize=src.getCellSize();
  double x=src.getWest() + cellSize * col;
  double y=src.getNorth() - cellSize * row;
  if (isFlat(col,row)) {
    nzGrid.setValue(1f,col,row);
    return;
  }
  double w=src.getValue(col - 1,row);
  double e=src.getValue(col + 1,row);
  double s=src.getValue(col,row + 1);
  double n=src.getValue(col,row - 1);
  double cntrNx=w - e;
  double cntrNy=s - n;
  double cntrNZ=2 * src.getProjectedCellSize();
  double nL=Math.sqrt(cntrNx * cntrNx + cntrNy * cntrNy + cntrNZ * cntrNZ);
  cntrNx/=nL;
  cntrNy/=nL;
  cntrNZ/=nL;
  if (Double.isNaN(cntrNx)) {
    nzGrid.setValue(1f,col,row);
    return;
  }
  double centralW=gaussianWeights[0];
  double downhillTotalW=0;
  double uphillTotalW=0;
  double uphillNx=0, uphillNy=0, uphillNz=0;
  double downhillNx=0, downhillNy=0, downhillNz=0;
  double[] normal=new double[3];
  iter.reset(x,y);
  float cntrVal=src.getValue(col,row);
  double relativeVal=(cntrVal - min) / (max - min);
  double uphillWeightScale=uphillWeightScale(relativeVal);
  int hl=(int)Math.ceil(halfLineLength);
  for (int i=1; i <= hl; i++) {
    if (iter.nextUphill() == false) {
      break;
    }
    if (normal(src,iter.getX(),iter.getY(),normal) == false) {
      break;
    }
    double weight=gaussianWeights[i] * uphillWeightScale;
    uphillTotalW+=weight;
    uphillNx+=weight * normal[0];
    uphillNy+=weight * normal[1];
    uphillNz+=weight * normal[2];
  }
  iter.reset(x,y);
  for (int i=1; i <= hl; i++) {
    if (iter.nextDownhill() == false) {
      break;
    }
    if (normal(src,iter.getX(),iter.getY(),normal) == false) {
      break;
    }
    double weight=gaussianWeights[i];
    downhillTotalW+=weight;
    downhillNx+=weight * normal[0];
    downhillNy+=weight * normal[1];
    downhillNz+=weight * normal[2];
  }
  double totalW=centralW + downhillTotalW + uphillTotalW;
  double nx=(centralW * cntrNx + downhillNx + uphillNx) / totalW;
  double ny=(centralW * cntrNy + downhillNy + uphillNy) / totalW;
  double nz=(centralW * cntrNZ + downhillNz + uphillNz) / totalW;
  nxGrid.setValue(nx,col,row);
  nyGrid.setValue(ny,col,row);
  nzGrid.setValue(nz,col,row);
}

Fixed version (ground truth):
/** 
 * Line integral convolution of normal vectors with uniform sampling distance and Gaussian weights along a line of steepest slope in uphill and downhill direction.
 * @param grid scalar field
 * @param row start position row
 * @param col start position column
 */
private void lic(SlopeLineIterator iter,Grid src,int row,int col){
  double cellSize=src.getCellSize();
  double x=src.getWest() + cellSize * col;
  double y=src.getNorth() - cellSize * row;
  if (isFlat(col,row)) {
    nzGrid.setValue(1f,col,row);
    return;
  }
  double w=src.getValue(col - 1,row);
  double e=src.getValue(col + 1,row);
  double s=src.getValue(col,row + 1);
  double n=src.getValue(col,row - 1);
  double cntrNx=w - e;
  double cntrNy=s - n;
  double cntrNZ=2 * src.getProjectedCellSize();
  double nL=Math.sqrt(cntrNx * cntrNx + cntrNy * cntrNy + cntrNZ * cntrNZ);
  cntrNx/=nL;
  cntrNy/=nL;
  cntrNZ/=nL;
  if (Double.isNaN(cntrNx) || Double.isNaN(cntrNy)) {
    nzGrid.setValue(1f,col,row);
    return;
  }
  double centralW=gaussianWeights[0];
  double downhillTotalW=0;
  double uphillTotalW=0;
  double uphillNx=0, uphillNy=0, uphillNz=0;
  double downhillNx=0, downhillNy=0, downhillNz=0;
  double[] normal=new double[3];
  iter.reset(x,y);
  float cntrVal=src.getValue(col,row);
  double relativeVal=(cntrVal - min) / (max - min);
  double uphillWeightScale=uphillWeightScale(relativeVal);
  int hl=(int)Math.ceil(halfLineLength);
  for (int i=1; i <= hl; i++) {
    if (iter.nextUphill() == false) {
      break;
    }
    if (normal(src,iter.getX(),iter.getY(),normal) == false) {
      break;
    }
    double weight=gaussianWeights[i] * uphillWeightScale;
    uphillTotalW+=weight;
    uphillNx+=weight * normal[0];
    uphillNy+=weight * normal[1];
    uphillNz+=weight * normal[2];
  }
  iter.reset(x,y);
  for (int i=1; i <= hl; i++) {
    if (iter.nextDownhill() == false) {
      break;
    }
    if (normal(src,iter.getX(),iter.getY(),normal) == false) {
      break;
    }
    double weight=gaussianWeights[i];
    downhillTotalW+=weight;
    downhillNx+=weight * normal[0];
    downhillNy+=weight * normal[1];
    downhillNz+=weight * normal[2];
  }
  double totalW=centralW + downhillTotalW + uphillTotalW;
  double nx=(centralW * cntrNx + downhillNx + uphillNx) / totalW;
  double ny=(centralW * cntrNy + downhillNy + uphillNy) / totalW;
  double nz=(centralW * cntrNZ + downhillNz + uphillNz) / totalW;
  nxGrid.setValue(nx,col,row);
  nyGrid.setValue(ny,col,row);
  nzGrid.setValue(nz,col,row);
}