View Raw SPL
/*****************************************************************************
* *
* SGRID.SPL Copyright (C) 1997 DSP Development Corporation *
* All Rights Reserved *
* *
* Author: Randy Race *
* *
* Synopsis: Grids XYZ data using cubic splines *
* *
* Revisions: 10 Oct 1997 RRR Creation *
* *
*****************************************************************************/
#include
#if @HELP_SGRID
SGRID
Purpose: Grids XYZ data using spline interpolation
Syntax: SGRID(x, y, z, xi, yi)
x - a series, x or horizontal range
y - a series, y or vertical range
z - a series, z or height data
xi - an optional series, output x range
yi - an optional series, output y range
Returns: An array
Example:
(x, y) = fxyvals(-10, 10, 2, -10, 10, 2)
z = cos(x*y)
xyz = sgrid(x[..], y[..], z[..], -10..0.5..10, -10..0.5..10)
Grids the function cos(x*y) over the range -10 to 10
interpolated with an increment of 0.5.
Remarks:
SGRID first interpolates in the direction with the most
variability. The output X and Y ranges (xi, yi)
are determined from the data if not specified.
See Also
Spline
#endif
sgrid(x, y, z, xi, yi)
{
local trans, zi;
/* interpolate in the most variable dimension first */
trans = distinct_vals(x) > distinct_vals(y);
if (trans)
{
zi = splinegrid(y, x, z, yi, xi)';
}
else
{
zi = splinegrid(x, y, z, xi, yi);
}
return(zi);
}
splinegrid(x, y, z, xi, yi)
{
local yinc, yidx, ys, yc;
local xinc, xidx, xs, xval;
local zi, zs, zval;
/* if interpolated range not specified, determine from data */
if (argc < 4)
{
(xi, yi, xinc, yinc) = xyz_xyvals(x, y);
}
else
{
/* get increment from range - assumes ranges are sorted */
xinc = xi[2] - xi[1];
yinc = yi[2] - yi[1];
}
/* sort based on Y data */
yidx = grade(y, 1);
ys = reorder(y, yidx);
xs = reorder(x, yidx);
zs = reorder(z, yidx);
/* find non-duplicate Y values */
yc = extract(ys - delay(ys, 1), 2, -1);
/* generate the distinct Y indices and prepend a 0 */
yidx = {0, delete(1..length(y), yc == 0.0)};
/*
* generate the lengths of constant Y's by raveling into a
* 2 x n array and subtracting the indices - yc is a series
* that contains the lengths of each column of constant Y
*/
yc = ravel(yidx, 2, 1, 1);
yc = (yc[2, ..] - yc[1, ..])';
/* order X and Z based on constant Y lenghts */
xval = reshape(xs, yc);
if (min(collength(xval)') < 2)
{
error("splinegrid - require 2 or more constant Y samples of X");
}
xidx = grade(xval, 1);
xval = reorder(xval, xidx);
zval = reshape(zs, yc);
zval = reorder(zval, xidx);
/* spline in X direction */
zi = spline(xval, zval, xi)';
/* Y values */
yval = ravel(rep(ys[extract(yidx, 2, -1)], numcols(zi)), numrows(zi));
/* spline in Y direction */
zi = spline(yval, zi, yi)';
/* Z data units */
setdeltax(zi, xinc);
setxoffset(zi, min(xi));
sethunits(zi, getvunits(x));
setdeltay(zi, yinc);
setyoffset(zi, min(yi));
setvunits(zi, getvunits(y));
return(zi);
}
/* find xy grid from xyz data */
xyz_xyvals(x, y)
{
local j, xinc, yinc, xind, yind, xyz;
/* minimum x and y increment */
xinc = mininc(x);
yinc = mininc(y);
/* length of x and y data */
xdim = dim(x);
ydim = dim(y);
/* generate x and y series */
xvals = min(x) + (0..(xdim - 1)) * xinc;
yvals = min(y) + (0..(ydim - 1)) * yinc;
return(xvals, yvals, xinc, yinc);
}
/* minimum increment from non-monotonic data */
mininc(s)
{
local t;
t = sort(s, 1);
t = extract(t - delay(t, 1), 2, length(t) - 1);
t = delete(t, t == 0);
return(min(t), max(t));
}
/* range from non-monotonic data */
dim(s)
{
local dim, inc;
inc = mininc(s);
if (inc > 0)
{
dim = 1 + ceil((max(s) - min(s)) / inc);
}
else dim = 0;
return(castint(dim));
}
/* number of non-duplicate values in a series */
distinct_vals(s)
{
s = sort(s, 1);
s = s - delay(s, 1);
return(length(delete(s, s == 0.0)));
}