// // GriddedSet.java // /* VisAD system for interactive analysis and visualization of numerical data. Copyright (C) 1996 - 1999 Bill Hibbard, Curtis Rueden, Tom Rink, Dave Glowacki, Steve Emmerson, Tom Whittaker, Don Murray, and Tommy Jasmin. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ package visad; /** GriddedSet is implemented by those Set sub-classes whose samples lie on a rectangular grid topology (but note the geometry need not be rectangular). It is a M-dimensional array of points in R^N where ManifoldDimension = M <= N = DomainDimension.

The order of the samples is the rasterization of the orders of the 1D components, with the first component increasing fastest. For more detail, see the example in Linear2DSet.java.

Grid coordinates are zero-based and in the range -0.5 to length-0.5 i.e., there are "length" intervals of length 1.0, the first centered on 0.0 and the last centered on length-1.0 points outside this range are indicated by the grid coordinate Double.NaN.

*/ public class GriddedSet extends SampledSet { int[] Lengths; // error tolerance for Newton's method solvers // not static because may become data dependent float EPS = (float) 1.0E-15; // Pos records the grid's orientation // (i.e., the sign of the cross-products of the grid edges) boolean Pos; /** construct a GriddedSet with samples */ public GriddedSet(MathType type, float[][] samples, int[] lengths) throws VisADException { this(type, samples, lengths, null, null, null, true); } /** construct a GriddedSet with samples and non-default CoordinateSystem */ public GriddedSet(MathType type, float[][] samples, int[] lengths, CoordinateSystem coord_sys, Unit[] units, ErrorEstimate[] errors) throws VisADException { this(type, samples, lengths, coord_sys, units, errors, true); } GriddedSet(MathType type, float[][] samples, int[] lengths, CoordinateSystem coord_sys, Unit[] units, ErrorEstimate[] errors, boolean copy) throws VisADException { super(type, lengths.length, coord_sys, units, errors); init_lengths(lengths); if (samples == null ) { Samples = null; } else { init_samples(samples, copy); } } private void init_lengths(int[] lengths) throws VisADException { Lengths = new int[ManifoldDimension]; Length = 1; for (int j=0; j domain_dimension) { throw new SetException("GriddedSet.create: manifold_dimension greater " + "than domain_dimension"); } switch (domain_dimension) { case 1: return new Gridded1DSet(type, samples, lengths[0], coord_sys, units, errors, copy); case 2: if (manifold_dimension == 1) { return new Gridded2DSet(type, samples, lengths[0], coord_sys, units, errors, copy); } else { return new Gridded2DSet(type, samples, lengths[0], lengths[1], coord_sys, units, errors, copy); } case 3: if (manifold_dimension == 1) { return new Gridded3DSet(type, samples, lengths[0], coord_sys, units, errors, copy); } else if (manifold_dimension == 2) { return new Gridded3DSet(type, samples, lengths[0], lengths[1], coord_sys, units, errors, copy); } else { return new Gridded3DSet(type, samples, lengths[0], lengths[1], lengths[2], coord_sys, units, errors, copy); } default: return new GriddedSet(type, samples, lengths, coord_sys, units, errors, copy); } } public Set makeSpatial(SetType type, float[][] samples) throws VisADException { return create(type, samples, Lengths, null, null, null, false); } public int getLength(int i) { return Lengths[i]; } public int[] getLengths() { int[] lens = new int[Lengths.length]; for (int i=0; i=0; i--) { wedge[k] = wedge[i] + base; k++; } } else { for (i=0; i=0; j--) { if (Double.isNaN(grid[j][i])) { k = -1; break; } k = ((int) (grid[j][i] + 0.5)) + Lengths[j] * k; } index[i] = k; } return index; } /** transform an array of non-integer grid coordinates to an array of values in R^DomainDimension */ public float[][] gridToValue(float[][] grid) throws VisADException { for (int j=0; j 1"); } } throw new UnimplementedException("GriddedSet.gridToValue"); } /** transform an array of values in R^DomainDimension to an array of non-integer grid coordinates */ public float[][] valueToGrid(float[][] value) throws VisADException { for (int j=0; j 1"); } } throw new UnimplementedException("GriddedSet.valueToGrid"); } /** for each of an array of values in R^DomainDimension, compute an array of 1-D indices and an array of weights, to be used for interpolation; indices[i] and weights[i] are null if i-th value is outside grid (i.e., if no interpolation is possible) */ public void valueToInterp(float[][] value, int[][] indices, float[][] weights) throws VisADException { if (value.length != DomainDimension) { throw new SetException("GriddedSet.valueToInterp: bad dimension"); } int length = value[0].length; // number of values if (indices.length != length || weights.length != length) { throw new SetException("GriddedSet.valueToInterp: lengths don't match"); } float[][] grid = valueToGrid(value); // convert value array to grid coord array int i, j, k; // loop indices int lis; // temporary length of is & cs int length_is; // final length of is & cs, varies by i int isoff; // offset along one grid dimension float a, b; // weights along one grid dimension; a + b = 1.0 int[] is; // array of indices, becomes part of indices float[] cs; // array of coefficients, become part of weights int base; // base index, as would be returned by valueToIndex int[] l = new int[ManifoldDimension]; // integer 'factors' of base float[] c = new float[ManifoldDimension]; // fractions with l; -0.5 <= c <= 0.5 // array of index offsets by grid dimension int[] off = new int[ManifoldDimension]; off[0] = 1; for (j=1; j= 0.0))) { // only interp along ManifoldDimension-1 if between two valid grid coords length_is *= 2; } base = l[ManifoldDimension-1]; if (base >= Lengths[ManifoldDimension-1]) base = -1; } for (j=ManifoldDimension-2; j>=0 && base>=0; j--) { if (Double.isNaN(grid[j][i])) { base = -1; } else { l[j] = (int) (grid[j][i] + 0.5); if (l[j] == Lengths[j]) l[j]--; // WLH 23 Dec 99 c[j] = grid[j][i] - ((float) l[j]); if (!((l[j] == 0 && c[j] <= 0.0) || (l[j] == Lengths[j] - 1 && c[j] >= 0.0))) { // only interp along dimension j if between two valid grid coords length_is *= 2; } base = l[j] + Lengths[j] * base; if (l[j] < 0 || l[j] >= Lengths[j]) base = -1; } } if (base < 0) { // value is out of grid so return null is = null; cs = null; } else { // create is & cs of proper length, and init first element is = new int[length_is]; cs = new float[length_is]; is[0] = base; cs[0] = 1.0f; lis = 1; for (j=0; j= 0.0))) { // only interp along dimension j if between two valid grid coords if (c[j] >= 0.0) { // grid coord above base isoff = off[j]; a = 1.0f - c[j]; b = c[j]; } else { // grid coord below base isoff = -off[j]; a = 1.0f + c[j]; b = -c[j]; } // float is & cs; adjust new offsets; split weights for (k=0; k"+ ManifoldDimension+" not currently implemented" ); } } public int[][] getNeighbors( int manifoldIndex ) { int[][] neighbors = new int[ Length ][2]; int[] m_coords = new int[ ManifoldDimension ]; int[][] indeces = new int[2][ ManifoldDimension ]; int ii_tmp, idx_u, idx_d, mm, tt, ii, jj, kk, k; for ( ii = 0; ii < Length; ii++ ) { //- get the manifold coordinates for each index -* ii_tmp = ii; for ( jj = 0; jj < (ManifoldDimension-1); jj++ ) { m_coords[jj] = ii_tmp % Lengths[jj]; ii_tmp /= Lengths[jj]; } m_coords[ManifoldDimension-1] = ii_tmp; //- get coordinates of two neighbors on each side -* for ( kk = 0; kk < 2; kk++) { for ( jj = 0; jj < ManifoldDimension; jj++) { indeces[kk][jj] = m_coords[jj]; } } idx_u = m_coords[ manifoldIndex ] + 1; idx_d = m_coords[ manifoldIndex ] - 1; indeces[1][manifoldIndex] = idx_u; indeces[0][manifoldIndex] = idx_d; if ( idx_u >= Lengths[manifoldIndex] ) { indeces[1][manifoldIndex] = -1; } else if ( idx_d < 0 ) { indeces[0][manifoldIndex] = -1; } //- compute index for each new coordinates -* for ( kk = 0; kk < 2; kk++ ) { if ( indeces[kk][manifoldIndex] != -1 ) { ii_tmp = 0; for ( mm = (ManifoldDimension-1); mm>=0; mm--) { k = indeces[kk][mm]; for ( tt = 0; tt < mm; tt++ ) { k = k*Lengths[tt]; } ii_tmp += k; } neighbors[ii][kk] = ii_tmp; } else { neighbors[ii][kk] = -1; } } } return neighbors; } public boolean equals(Object set) { if (!(set instanceof GriddedSet) || set == null || set instanceof LinearSet || set instanceof Gridded1DDoubleSet) return false; if (this == set) return true; if (testNotEqualsCache((Set) set)) return false; if (testEqualsCache((Set) set)) return true; if (!equalUnitAndCS((Set) set)) return false; try { int i, j; if (DomainDimension != ((GriddedSet) set).getDimension() || ManifoldDimension != ((GriddedSet) set).getManifoldDimension() || Length != ((GriddedSet) set).getLength()) return false; for (j=0; j