// // IrregularSet.java // /* VisAD system for interactive analysis and visualization of numerical data. Copyright (C) 1996 - 2017 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; /** IrregularSet is implemented by those Set sub-classes whose samples do not form any ordered pattern. It is a M-dimensional array of points in R^N where ManifoldDimension = M <= N = DomainDimension.<P> 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.<P> */ public class IrregularSet extends SampledSet { public Delaunay Delan = null; /** oldToNew and newToOld used when ManifoldDimension = 1 but DomainDimension > 1 */ /** maps old samples indices to sorted samples indices */ int[] oldToNew; /** maps sorted samples indices to old samples indices */ int[] newToOld; /** construct an IrregularSet */ public IrregularSet(MathType type, float[][] samples) throws VisADException { this(type, samples, samples.length, null, null, null, null, true); } /** construct an IrregularSet with non-default CoordinateSystem */ public IrregularSet(MathType type, float[][] samples, CoordinateSystem coord_sys, Unit[] units, ErrorEstimate[] errors) throws VisADException { this (type, samples, samples.length, coord_sys, units, errors, null, true); } /** construct an IrregularSet with non-default Delaunay */ public IrregularSet(MathType type, float[][] samples, Delaunay delan) throws VisADException { this(type, samples, samples.length, null, null, null, delan, true); } /** construct an IrregularSet with non-default CoordinateSystem and non-default Delaunay */ public IrregularSet(MathType type, float[][] samples, CoordinateSystem coord_sys, Unit[] units, ErrorEstimate[] errors, Delaunay delan) throws VisADException { this(type, samples, samples.length, coord_sys, units, errors, delan, true); } /** construct an IrregularSet with ManifoldDimension != DomainDimension, with non-default CoordinateSystem, and with non-default Delaunay */ public IrregularSet(MathType type, float[][] samples, int manifold_dimension, CoordinateSystem coord_sys, Unit[] units, ErrorEstimate[] errors, Delaunay delan) throws VisADException { this(type, samples, manifold_dimension, coord_sys, units, errors, delan, true); } public IrregularSet(MathType type, float[][] samples, int manifold_dimension, CoordinateSystem coord_sys, Unit[] units, ErrorEstimate[] errors, Delaunay delan, boolean copy) throws VisADException { super(type, manifold_dimension, coord_sys, units, errors); if (samples == null ) { throw new SetException("IrregularSet: samples cannot be null"); } init_samples(samples, copy); // initialize Delaunay triangulation structure if (ManifoldDimension > 1) { if (delan != null) { if (copy) Delan = (Delaunay) delan.clone(); else Delan = delan; } else Delan = Delaunay.factory(samples, false); } } /** convert an array of 1-D indices to an array of values in R^DomainDimension */ public float[][] indexToValue(int[] index) throws VisADException { float[][] value = new float[DomainDimension][index.length]; float[][]mySamples = getMySamples(); for (int i=0; i<index.length; i++) { if ( (index[i] >= 0) && (index[i] < Length) ) { for (int j=0; j<DomainDimension; j++) { value[j][i] = mySamples[j][index[i]]; } } else { for (int j=0; j<DomainDimension; j++) { value[j][i] = Float.NaN; } } } return value; } /** convert an array of values in R^DomainDimension to an array of 1-D indices */ public int[] valueToIndex(float[][] value) throws VisADException { throw new UnimplementedException("IrregularSet.valueToIndex"); } /** 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 no interpolation is possible */ public void valueToInterp(float[][] value, int[][] indices, float weights[][]) throws VisADException { throw new UnimplementedException("IrregularSet.valueToInterp"); } /** * Returns the indexes of neighboring samples for all samples. * * @param neighbors The indexes of the neighboring points. On * input, <code>neighbors.length</code> * must be greater than or equal to * <code>getLength()</code>. On output, * <code>neighbors[i][j]</code> will be the index * of the <code>j</code>th neighboring sample of * sample <code>i</code>. * @throws VisADException if a VisAD failure occurs. */ public void getNeighbors( int[][] neighbors ) throws VisADException { if ( ManifoldDimension == 1 ) { neighbors[0] = new int[2]; neighbors[Length - 1] = new int[2]; neighbors[0][0] = 1; neighbors[Length - 1][0] = Length - 2; for ( int ii = 1; ii < (Length - 1); ii++ ) { neighbors[ii] = new int[2]; neighbors[ii][0] = ii - 1; neighbors[ii][0] = ii + 1; } } else if ( ManifoldDimension < 4 ) { int[][] Vertices = Delan.Vertices; int[][] Tri = Delan.Tri; int n_samples = Vertices.length; int n_triangles; int cnt, ii, jj, kk, tt, index; int[] indeces; for ( ii = 0; ii < n_samples; ii++ ) { indeces = new int[n_samples]; n_triangles = Vertices[ii].length; for ( jj = 0; jj < n_triangles; jj++ ) { for ( kk = 0; kk < Tri[ Vertices[ii][jj] ].length; kk++ ) { index = Tri[ Vertices[ii][jj] ][kk]; if ( index != ii ) indeces[ index ]++; } } cnt = 0; for ( tt = 0; tt < n_samples; tt++ ) { if ( indeces[tt] > 0 ) cnt++; } neighbors[ii] = new int[ cnt ]; cnt = 0; for ( tt = 0; tt < n_samples; tt++ ) { if ( indeces[tt] > 0 ) { neighbors[ii][cnt] = tt; cnt++; } } indeces = null; } } else { throw new UnimplementedException("getNeighbors(): ManifoldDimension > 3 "); } } public boolean equals(Object set) { if (!(set instanceof IrregularSet) || set == null || set instanceof LinearSet) 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 != ((IrregularSet) set).getDimension() || ManifoldDimension != ((IrregularSet) set).getManifoldDimension() || Length != ((IrregularSet) set).getLength()) return false; // Sets are immutable, so no need for 'synchronized' float[][]mySamples = getMySamples(); float[][] samples = ((IrregularSet) set).getSamples(false); for (j=0; j<DomainDimension; j++) { for (i=0; i<Length; i++) { if (mySamples[j][i] != samples[j][i]) { addNotEqualsCache((Set) set); return false; } } } addEqualsCache((Set) set); return true; } catch (VisADException e) { return false; } } /** * Clones this instance. * * @return A clone of this instance. */ public Object clone() { IrregularSet clone = (IrregularSet)super.clone(); if (Delan != null) clone.Delan = (Delaunay)Delan.clone(); return clone; } public Object cloneButType(MathType type) throws VisADException { return new IrregularSet(type, getMySamples(), DomainCoordinateSystem, SetUnits, SetErrors, Delan); } public String longString(String pre) throws VisADException { String s; int j; if (DomainDimension == ManifoldDimension) { s = pre + getClass().getName() + ": Dimension = " + DomainDimension + " Length = " + Length + "\n"; for (j=0; j<DomainDimension; j++) { s = s + pre + " Dimension " + j + ":" + " Range = " + Low[j] + " to " + Hi[j] + "\n"; } } else { s = pre + getClass().getName() + ": DomainDimension = " + DomainDimension + " ManifoldDimension = " + ManifoldDimension + " Length = " + Length + "\n"; for (j=0; j<DomainDimension; j++) { s = s + pre + " DomainDimension " + j + ":" + " Range = " + Low[j] + " to " + Hi[j] + "\n"; } } return s; } }