/* * 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.numeric; /** The collection of all interpolation operators for Grids. */ public abstract class InterpolationOperators { /////////////////////////////////////////////////////////////////////// // Linear interpolation of Grids // /////////////////////////////////////////////////////////////////////// public static enum boundaryHandling { ZEROPAD, REPLICATE } private static Integer correctBoundsOfIndex(int idx, int gridSize, boundaryHandling bounds){ Integer retVal = idx; switch (bounds) { case ZEROPAD: if (idx < 0 || idx > gridSize-1) retVal = null; break; case REPLICATE: if (idx < 0) retVal = 0; if (idx > gridSize-1) retVal = gridSize-1; break; default: if (idx < 0 || idx > gridSize-1) retVal = null; break; } return retVal; } /** Linear interpolation of a 1D Grid */ public static float interpolateLinear(final Grid1D grid, double i){ return interpolateLinear(grid, i, boundaryHandling.ZEROPAD); } /** Linear interpolation of a 1D Grid */ public static float interpolateLinear(final Grid1D grid, double i, boundaryHandling bounds) { Integer lower = (int) Math.floor(i); double d = i - lower; // d is in [0, 1) Integer lowerPlusOne = lower+1; lower = correctBoundsOfIndex(lower, grid.getSize()[0], bounds); lowerPlusOne = correctBoundsOfIndex(lowerPlusOne, grid.getSize()[0], bounds); return (float) ( (1.0-d)*((lower!=null) ? grid.getAtIndex(lower) : 0.0) + ((d != 0.0) ? d*((lowerPlusOne != null) ? grid.getAtIndex(lowerPlusOne): 0.0) : 0.0) ); } /** Linear interpolation of a 2D Grid */ public static float interpolateLinear(final Grid2D grid, double x, double y){ return interpolateLinear(grid, x, y, boundaryHandling.ZEROPAD); } /** Linear interpolation of a 2D Grid */ public static float interpolateLinear(final Grid2D grid, double x, double y, boundaryHandling bounds) { if (grid == null) return 0; Integer lower = (int) Math.floor(y); double d = y - lower; // d is in [0, 1) Integer lowerPlusOne = lower+1; lower = correctBoundsOfIndex(lower, grid.getSize()[1], bounds); lowerPlusOne = correctBoundsOfIndex(lowerPlusOne, grid.getSize()[1], bounds); return (float) ( (1.0-d)*((lower!=null) ? interpolateLinear(grid.getSubGrid(lower), x, bounds) : 0.0) + ((d != 0.0) ? d*((lowerPlusOne != null) ? interpolateLinear(grid.getSubGrid(lowerPlusOne), x, bounds) : 0.0) : 0.0) ); } /** Linear interpolation of a 3D Grid */ public static float interpolateLinear(final Grid3D grid, double z, double x, double y){ return interpolateLinear(grid, z, x, y, boundaryHandling.ZEROPAD); } /** Linear interpolation of a 3D Grid */ public static float interpolateLinear(final Grid3D grid, double z, double x, double y, boundaryHandling bounds) { Integer lower = (int) Math.floor(z); double d = z - lower; // d is in [0, 1) Integer lowerPlusOne = lower+1; lower = correctBoundsOfIndex(lower, grid.getSize()[2], bounds); lowerPlusOne = correctBoundsOfIndex(lowerPlusOne, grid.getSize()[2], bounds); return (float) ( (1.0-d)*((lower!=null) ? interpolateLinear(grid.getSubGrid(lower), x, y, bounds) : 0.0) + ((d != 0.0) ? d*((lowerPlusOne != null) ? interpolateLinear(grid.getSubGrid(lowerPlusOne), x, y, bounds) : 0.0) : 0.0) ); } /////////////////////////////////////////////////////////////////////// // Interpolated updates into Grids // // (These methods "spread out" an additive update to a grid using // // the same weighting factors as for interpolation.) // /////////////////////////////////////////////////////////////////////// /** Linear extrapolation into a 1D Grid */ public static void addInterpolateLinear(final Grid1D grid, double x, float val) { int lower = (int) Math.floor(x); double d = x - lower; grid.setAtIndex(lower, grid.getAtIndex(lower) + (float) ((1.0-d)*val)); if (d != 0.0) grid.setAtIndex(lower+1, grid.getAtIndex(lower+1) + (float) (d*val)); } /** Linear extrapolation into a 2D Grid */ public static void addInterpolateLinear(final Grid2D grid, double x, double y, float val) { int lower = (int) Math.floor(y); double d = y - lower; addInterpolateLinear(grid.getSubGrid(lower), x, (float) ((1.0-d)*val)); if (d != 0.0) addInterpolateLinear(grid.getSubGrid(lower+1), x, (float) (d*val)); } /** Linear extrapolation into a 3D Grid */ public static void addInterpolateLinear(final Grid3D grid, double x, double y, double z, float val) { int lower = (int) Math.floor(z); double d = z - lower; addInterpolateLinear(grid.getSubGrid(lower), x, y, (float) ((1.0-d)*val)); if (d != 0.0) addInterpolateLinear(grid.getSubGrid(lower+1), x, y, (float) (d*val)); } }