/**************************************************************************** Copyright (c) 2009, Colorado School of Mines and others. All rights reserved. This program and accompanying materials are made available under the terms of the Common Public License - v1.0, which accompanies this distribution, and is available at http://www.eclipse.org/legal/cpl-v10.html ****************************************************************************/ package edu.mines.jtk.interp; import edu.mines.jtk.dsp.*; import edu.mines.jtk.util.Check; import static edu.mines.jtk.util.ArrayMath.*; /** * Tensor-guided blended neighbor gridding in 2D. * Gridding is interpolation of a set of known sample values on a * uniformly sampled grid. Here the interpolation is performed by * a two-step blended neighbor process described by Hale (2009). *
* The first step is to compute for all samples the distance to the * nearest known sample and the value of that known sample. This first * step produces a distance map and a nearest-neighbor interpolant. *
* The second step is to blend (smooth) the nearest-neighbor interpolant, * where the extent of smoothing varies spatially and is proportional to * distances in the distance map. *
* In tensor-guided gridding, we replace distance with time. Time is a * simple term for non-Euclidean distance measured in a metric-tensor * field. So "nearest" now means nearest in time. In the first step we * compute a time map by solving an eikonal equation with coefficients * that may be both anisotropic and spatially varying. In the second * step, we blend the nearest-neighbor interpolant with an anisotropic * and spatially varying smoothing filter. *
* The default tensor field is homogeneous and isotropic. In this * special case, time is equivalent to distance, and tensor-guided * gridding is similar to gridding with Sibson's natural neighbor * interpolant. *
* Reference: * * Hale, D., 2009, Image-guided blended neighbor interpolation, CWP-634 * @author Dave Hale, Colorado School of Mines * @version 2009.07.21 */ public class BlendedGridder2 implements Gridder2 { /** * Constructs a gridder for default tensors. */ public BlendedGridder2() { this(null); } /** * Constructs a gridder for default tensors and specified samples. * The specified arrays are referenced; not copied. * @param f array of sample values f(x1,x2). * @param x1 array of sample x1 coordinates. * @param x2 array of sample x2 coordinates. */ public BlendedGridder2(float[] f, float[] x1, float[] x2) { this(null); setScattered(f,x1,x2); } /** * Constructs a gridder for the specified tensors. * @param tensors the tensors. */ public BlendedGridder2(Tensors2 tensors) { setTensors(tensors); } /** * Constructs a gridder for the specified tensors and samples. * The specified arrays are referenced; not copied. * @param tensors the tensors. * @param f array of sample values f(x1,x2). * @param x1 array of sample x1 coordinates. * @param x2 array of sample x2 coordinates. */ public BlendedGridder2( Tensors2 tensors, float[] f, float[] x1, float[] x2) { setTensors(tensors); setScattered(f,x1,x2); } /** * Sets the tensor field used by this gridder. * The default is a homogeneous and isotropic tensor field. * @param tensors the tensors; null for default tensors. */ public void setTensors(Tensors2 tensors) { _tensors = tensors; if (_tensors==null) { _tensors = new Tensors2() { public void getTensor(int i1, int i2, float[] d) { d[0] = 1.0f; d[1] = 0.0f; d[2] = 1.0f; } }; } } /** * Enables or disables blending in {@link #grid(Sampling,Sampling)}. * If true (the default), that method will perform both of the two * steps described; that is, it will blend (smooth) after computing * the nearest neighbor interpolant. If false, that method will perform * only the first step and return the nearest neighbor interpolant. The * default is that blending is enabled. * @param blending true, for blending; false, otherwise. */ public void setBlending(boolean blending) { _blending = blending; } /** * Sets the local diffusion kernel used to perform blending. * The default kernel uses a 2x2 stencil to compute derivatives. * @param ldk the local diffusion kernel. */ public void setBlendingKernel(LocalDiffusionKernel ldk) { _ldk = ldk; } /** * Sets the smoothness of the interpolation of gridded values. * The default is 0.5, which yields an interpolant with linear precision. * Larger values yield smoother interpolants with plateaus at known samples. */ public void setSmoothness(double smoothness) { _c = 0.25f/(float)smoothness; } /** * Sets the maximum time computed by this gridder. The gridder has * linear precision where times are less than the maximum time. * @param tmax the maximum time. */ public void setTimeMax(double tmax) { _tmax = (float)tmax; } /** * Computes gridded values using nearest neighbors. * Gridded values in the array p are computed for only unknown * samples with value equal to the specified null value. Any * known (non-null) sample values in the array p are not changed. *
* This method also computes and returns an array of times to
* nearest-neighbor samples. Times are zero for known samples
* and are positive for gridded samples.
* @param pnull the null value representing unknown samples.
* @param p array of sample values to be gridded.
* @return array of times to nearest known samples.
*/
public float[][] gridNearest(float pnull, float[][] p) {
int n1 = p[0].length;
int n2 = p.length;
// Make array of times, zero for samples with non-null values.
// Also, count the number of marks that we will need.
int nmark = 0;
float[][] t = new float[n2][n1];
float tnull = -FLT_MAX;
for (int i2=0; i2