content: /*
   * Copyright (C) 2010-2014 - Andreas Maier, Andreas Keil 
   * CONRAD is developed as an Open Source project under the GNU General Public License (GPL).
   */
  package edu.stanford.rsl.conrad.data.generic;
  
  import edu.stanford.rsl.conrad.data.generic.datatypes.Gridable;
  
  
  /** The collection of all interpolation operators for Grids. */
  public abstract class GenericInterpolationOperators<T extends Gridable<T>> {
  
  
  	///////////////////////////////////////////////////////////////////////
  	// Linear interpolation of Grids                                     //
  	///////////////////////////////////////////////////////////////////////
  
  	protected abstract T getDefault();
  
  	/** Linear interpolation of an ND Grid */
  	public T interpolateLinear(final GenericGrid<T> grid, int currDim, double... idx) {
  		int lower = (int) Math.floor(idx[currDim]);
  		double d = idx[currDim] - lower; // d is in [0, 1)
  		if(currDim<=0){
  			int[] lowIdx = new int[idx.length];
  			int[] highIdx = new int[idx.length];
  			for (int i = 1; i < highIdx.length; i++) {
  				lowIdx[i] = (int)idx[i];
  				highIdx[i] = (int)idx[i];
  			}
  			lowIdx[0]=lower;
  			highIdx[0]=lower+1;
  			return grid.getValue(lowIdx).mul(1.0-d)
  					.add((d != 0.0) ? grid.getValue(highIdx).mul(d) : getDefault());
  		}
  
  		double[] lowIdx = new double[idx.length];
  		double[] highIdx = new double[idx.length];
  		System.arraycopy(idx, 0, lowIdx, 0, idx.length);
  		System.arraycopy(idx, 0, highIdx, 0, idx.length);
  		lowIdx[currDim]=lower;
  		highIdx[currDim]=lower+1;
  
  		return interpolateLinear(grid, currDim-1, lowIdx).mul((1.0-d))
  				.add((d != 0.0) ? interpolateLinear(grid, currDim-1, highIdx).mul(d) : getDefault());
  	}
  	
  	/** Linear interpolation of an ND Grid */
  	public T interpolateLinear(final GenericGrid<T> grid, double... idx) {
  		return interpolateLinear(grid, idx.length-1, idx);
  	}
  	
  	/** Linear interpolation of an ND Grid */
  	public void addInterpolateLinear(final GenericGrid<T> grid, int currDim, T val, double... idx) {
  		int lower = (int) Math.floor(idx[currDim]);
  		double d = idx[currDim] - lower; // d is in [0, 1)
  		
  		if(currDim<=0){
  			int[] lowIdx = new int[idx.length];
  			int[] highIdx = new int[idx.length];
  			for (int i = 1; i < highIdx.length; i++) {
  				lowIdx[i] = (int)idx[i];
  				highIdx[i] = (int)idx[i];
  			}
  			lowIdx[0]=lower;
  			highIdx[0]=lower+1;
  			grid.setValue(grid.getValue(lowIdx).add(val.mul(1.0-d)),lowIdx);
  			if (d != 0.0) grid.setValue(grid.getValue(highIdx).add(val.mul(d)));
  		}
  
  		double[] lowIdx = new double[idx.length];
  		double[] highIdx = new double[idx.length];
  		System.arraycopy(idx, 0, lowIdx, 0, idx.length);
  		System.arraycopy(idx, 0, highIdx, 0, idx.length);
  		lowIdx[currDim]=lower;
  		highIdx[currDim]=lower+1;
  
  		addInterpolateLinear(grid, currDim-1, val.mul((1.0-d)), lowIdx);
  		if (d != 0.0) addInterpolateLinear(grid, currDim-1, val.mul(d),highIdx);
  	}
  	
  	/** Linear extrapolation into an ND Grid */
  	public void addInterpolateLinear(final GenericGrid<T> grid, T val, double... idx) {
  		addInterpolateLinear(grid, idx.length-1, val, idx);
  	}
  }
  
  