//
// Vis5DForm.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.data.vis5d;
import visad.*;
import visad.java3d.*;
import visad.data.*;
import visad.data.units.Parser;
import visad.data.units.ParseException;
import visad.util.*;
import visad.jmet.DumpType;
import java.io.IOException;
import java.rmi.RemoteException;
import java.net.URL;
import java.util.Hashtable;
import java.util.Enumeration;
// JFC packages
import javax.swing.*;
import javax.swing.event.*;
// AWT packages
import java.awt.*;
import java.awt.event.*;
/**
Vis5DForm is the VisAD data format adapter for Vis5D files.<P>
*/
public class Vis5DForm extends Form implements FormFileInformer {
/** from vis5d-4.3/src/v5d.h */
private final int MAXVARS = 200;
private final int MAXTIMES = 400;
private final int MAXROWS = 400;
private final int MAXCOLUMNS = 400;
private final int MAXLEVELS = 400;
private final int MAXPROJARGS = MAXROWS+MAXCOLUMNS+1;
private final int MAXVERTARGS = MAXLEVELS+1;
private static int num = 0;
private static boolean loaded = false;
public Vis5DForm() {
super("Vis5DForm" + num++);
}
public boolean isThisType(String name) {
return name.endsWith(".v5d");
}
public boolean isThisType(byte[] block) {
String v5d = new String(block, 0, 3);
return v5d.equals("V5D");
}
public String[] getDefaultSuffixes() {
String[] suff = { "v5d" };
return suff;
}
public synchronized void save(String id, Data data, boolean replace)
throws BadFormException, IOException, RemoteException, VisADException {
throw new UnimplementedException("Vis5DForm.save");
}
public synchronized void add(String id, Data data, boolean replace)
throws BadFormException {
throw new BadFormException("Vis5DForm.add");
}
public synchronized DataImpl open(String id)
throws BadFormException, IOException, VisADException {
Set space_set;
V5DStruct vv;
FunctionType v5d_type;
int nvars;
int grid_size;
RealType[] vars;
if (id == null) {
throw new BadFormException("Vis5DForm.open: null name String");
}
byte[] name = id.getBytes();
int[] sizes = new int[5];
int[] map_proj = new int[1];
String[] varnames = new String[MAXVARS];
String[] varunits = new String[MAXVARS];
int[] n_levels = new int[MAXVARS];
int[] vert_sys = new int[1];
float[] vertargs = new float[MAXVERTARGS];
//-float[] times = new float[MAXTIMES];
double[] times = new double[MAXTIMES];
float[] projargs = new float[MAXPROJARGS];
vv = V5DStruct.v5d_open(name,
name.length,
sizes,
n_levels,
varnames,
varunits,
map_proj,
projargs,
vert_sys,
vertargs,
times);
if (sizes[0] < 1) {
throw new BadFormException("Vis5DForm.open: bad file");
}
//-System.out.println("proj: "+map_proj[0]);
int nr = sizes[0];
int nc = sizes[1];
int nl = sizes[2];
int ntimes = sizes[3];
nvars = sizes[4];
//-System.out.println("nr: "+nr);
//-System.out.println("nc: "+nc);
//-System.out.println("nl: "+nl);
//-System.out.println("ntimes: "+ntimes);
//-System.out.println("nvars: "+nvars);
RealType time = RealType.Time;
RealType row = RealType.getRealType("row");
RealType col = RealType.getRealType("col");
//RealType lev = RealType.getRealType("lev"); not used
vars = new RealType[nvars];
for (int i=0; i<nvars; i++) {
String unit_spec = varunits[i];
Unit unit = null;
if ( unit_spec != null ) {
try {
unit = Parser.parse(unit_spec);
}
catch (ParseException e) {
System.out.println(e.getMessage());
}
}
vars[i] = RealType.getRealType(varnames[i], unit);
if ( vars[i] == null ) {
vars[i] = RealType.getRealType("var"+i);
}
}
double[][] proj_args =
Set.floatToDouble(new float[][] {projargs});
double[][] vert_args =
Set.floatToDouble(new float[][] {vertargs});
CoordinateSystem coord_sys =
new Vis5DCoordinateSystem(map_proj[0], proj_args[0], nr, nc);
RealTupleType domain;
Vis5DVerticalSystem vert_coord_sys = null;
/*----------------------------------------------------------
Sort variables by n_levels. There should only be two
possibilities:
(1) all variables with same n_levels.
(2) some variables all with same n_levels, the rest with
only one level.
Throw BadFormException otherwise. */
Hashtable var_table = new Hashtable();
for (int i = 0; i < nvars; i++) {
var_table.put(new Integer(n_levels[i]), new Object());
}
int n_var_groups = var_table.size();
if ( n_var_groups > 2 ) {
throw
new BadFormException("more than two variable groups by n_levels");
}
else if ( n_var_groups == 0 ) {
throw
new BadFormException("n_var_groups == 0");
}
RealType[][] var_grps = new RealType[n_var_groups][];
RealType[] tmp_r = new RealType[nvars];
int[][] var_grps_indexes = new int[n_var_groups][];
int[] tmp_i = new int[nvars];
int[] var_grps_nlevels = new int[n_var_groups];
Enumeration en = var_table.keys();
for ( int grp = 0; grp < n_var_groups; grp++)
{
Integer key = (Integer)en.nextElement();
int cnt = 0;
for (int i = 0; i < nvars; i++) {
if ( n_levels[i] == key.intValue() ) {
tmp_r[cnt] = vars[i];
tmp_i[cnt] = i;
cnt++;
}
}
var_grps[grp] = new RealType[cnt];
System.arraycopy(tmp_r, 0, var_grps[grp], 0, cnt);
var_grps_indexes[grp] = new int[cnt];
System.arraycopy(tmp_i, 0, var_grps_indexes[grp], 0, cnt);
var_grps_nlevels[grp] = key.intValue();
}
/*---------------------------------------------------------*/
FunctionType[][] grid_type = new FunctionType[n_var_groups][];
Vis5DFile[][] v5dfile_s = new Vis5DFile[n_var_groups][];
int n_comps = 0;
for ( int grp = 0; grp < n_var_groups; grp++ )
{
RealType[] sub_vars = var_grps[grp];
int[] sub_vars_indexes = var_grps_indexes[grp];
nl = var_grps_nlevels[grp];
if (nl > 1) {
vert_coord_sys =
new Vis5DVerticalSystem(vert_sys[0], nl, vert_args[0]);
RealType height = vert_coord_sys.vert_type;
CoordinateSystem pcs =
new CachingCoordinateSystem(
new CartesianProductCoordinateSystem(
new CoordinateSystem[]
{coord_sys, vert_coord_sys.vert_cs}));
domain =
new RealTupleType( new RealType[] {row, col, height}, pcs, null);
/*
}
else {
domain = new RealTupleType(new RealType[] {row, col},
new CachingCoordinateSystem(coord_sys), null);
}
if (nl > 1)
{
*/
SampledSet vert_set = vert_coord_sys.vertSet;
/**- Maybe sometime in the future
RealTupleType row_col = new RealTupleType(new RealType[] {row, col});
SampledSet row_col_set = new Integer2DSet(row_col, nr, nc);
space_set = new ProductSet(domain,
new SampledSet[] {row_col_set, vert_set});
*/
if (vert_set instanceof Linear1DSet) {
space_set =
new Linear3DSet(domain,
new Linear1DSet[] {
new Integer1DSet(row, nr),
new Integer1DSet(col, nc),
(Linear1DSet) vert_set},
(CoordinateSystem) null,
new Unit[] {null, null, vert_coord_sys.vert_unit},
(ErrorEstimate[]) null);
}
else { // Gridde1DSet
float[][] vert_samples = vert_set.getSamples();
float[][] domain_samples = new float[3][nr*nc*nl];
int idx = 0;
for (int kk = 0; kk < nl; kk++) {
for (int jj = 0; jj < nc; jj++) {
for ( int ii = 0; ii < nr; ii++) {
domain_samples[0][idx] = ii;
domain_samples[1][idx] = jj;
domain_samples[2][idx] = vert_samples[0][kk];
idx++;
}
}
}
space_set =
//new Gridded3DSet(domain, domain_samples, nr, nc, nl);
new Gridded3DSet(
domain, domain_samples, nr, nc, nl,
(CoordinateSystem) null,
//new Unit[] {null, null, height.getDefaultUnit()},
new Unit[] {null, null, vert_coord_sys.vert_unit},
(ErrorEstimate[]) null);
}
grid_type[grp] = new FunctionType[sub_vars.length];
v5dfile_s[grp] = new Vis5DFile[sub_vars.length];
grid_size = nr * nc * nl;
for (int k = 0; k < sub_vars.length; k++) {
grid_type[grp][k] = new FunctionType(domain, sub_vars[k]);
v5dfile_s[grp][k] =
new Vis5DFile(id, vv, space_set,
grid_type[grp][k],
new RealType[] {sub_vars[k]},
new int[] {sub_vars_indexes[k]}, grid_size);
}
n_comps += grid_type[grp].length;
}
else
{
domain = new RealTupleType(new RealType[] {row, col},
new CachingCoordinateSystem(coord_sys), null);
space_set = new Integer2DSet(domain, nr, nc);
grid_type[grp] = new FunctionType[1];
v5dfile_s[grp] = new Vis5DFile[1];
RealTupleType range = new RealTupleType(sub_vars);
grid_type[grp][0] = new FunctionType(domain, range);
grid_size = nr * nc * nl;
v5dfile_s[grp][0] =
new Vis5DFile(id, vv, space_set,
grid_type[grp][0], sub_vars, sub_vars_indexes, grid_size);
n_comps += grid_type[grp].length;
}
}
RealTupleType time_domain = new RealTupleType(time);
MathType v5d_range;
MathType[] range_comps = new MathType[n_comps];
int cnt = 0;
for ( int grp = 0; grp < grid_type.length; grp++) {
for (int i = 0; i < grid_type[grp].length; i++) {
range_comps[cnt++] = grid_type[grp][i];
}
}
if (range_comps.length == 1) {
v5d_range = range_comps[0];
}
else {
v5d_range = new TupleType(range_comps);
}
v5d_type = new FunctionType(time_domain, v5d_range);
double[][] timeses = new double[1][ntimes];
for (int i=0; i<ntimes; i++) {
timeses[0][i] = times[i];
}
Unit v5d_time_unit = new OffsetUnit(
visad.data.units.UnitParser.encodeTimestamp(
1900, 1, 1, 0, 0, 0, 0), SI.second);
Gridded1DDoubleSet time_set =
new Gridded1DDoubleSet(time, timeses, ntimes,
null, new Unit[] {v5d_time_unit}, null);
FieldImpl v5d = new FieldImpl(v5d_type, time_set);
DataImpl range_data;
for (int i=0; i<ntimes; i++)
{
if (range_comps.length == 1) {
range_data = getFlatField(v5dfile_s[0][0], i);
}
else {
DataImpl[] datas = new DataImpl[range_comps.length];
cnt = 0;
for (int j = 0; j < v5dfile_s.length; j++) {
for (int k = 0; k < v5dfile_s[j].length; k++) {
datas[cnt++] = getFlatField(v5dfile_s[j][k], i);
}
}
range_data = new Tuple(datas, false);
}
v5d.setSample(i, range_data, false);
}
return v5d;
}
public FlatField getFlatField(Vis5DFile v5dfile, int time_idx)
throws VisADException, IOException, BadFormException
{
return makeFlatField(v5dfile, time_idx);
}
public static FlatField makeFlatField(Vis5DFile v5dfile, int time_idx)
throws VisADException, IOException, BadFormException
{
int nvars = v5dfile.nvars;
int grid_size = v5dfile.grid_size;
FunctionType grid_type = v5dfile.grid_type;
Set space_set = v5dfile.space_set;
V5DStruct vv = v5dfile.vv;
RealType[] vars = v5dfile.vars;
int[] vars_indexes = v5dfile.vars_indexes;
float[][] data = new float[nvars][grid_size];
Linear1DSet[] range_sets = new Linear1DSet[nvars];
for (int j=0; j<nvars; j++) {
float[] ranges = new float[2];
vv.v5d_read(time_idx, vars_indexes[j], ranges, data[j]);
if (ranges[0] >= 0.99E30 && ranges[1] <= -0.99E30) {
range_sets[j] = new Linear1DSet(0.0, 1.0, 255);
}
else {
if (ranges[0] > ranges[1]) {
throw new BadFormException("Vis5DForm.open: bad read " +
vars[j].getName());
}
range_sets[j] =
new Linear1DSet((double) ranges[0], (double) ranges[1], 255);
}
//- invert rows
float[] tmp_data = new float[grid_size];
int[] lens = ((GriddedSet)space_set).getLengths();
if ( lens.length == 2 ) {
int cnt = 0;
for ( int mm = 0; mm < lens[1]; mm++ ) {
int start = (mm+1)*lens[0] - 1;
for ( int nn = 0; nn < lens[0]; nn++ ) {
tmp_data[cnt++] = data[j][start--];
}
}
}
else if ( lens.length == 3 ) {
int cnt = 0;
for ( int ll = 0; ll < lens[2]; ll++ ) {
for ( int mm = 0; mm < lens[1]; mm++ ) {
int start = ((mm+1)*lens[0] - 1) + lens[0]*lens[1]*ll;
for ( int nn = 0; nn < lens[0]; nn++ ) {
tmp_data[cnt++] = data[j][start--];
}
}
}
}
System.arraycopy(tmp_data, 0, data[j], 0, grid_size);
tmp_data = null;
for (int k=0; k<grid_size; k++) {
if (data[j][k] > 0.5e35) data[j][k] = Float.NaN;
}
}
// FlatField grid =
// new FlatField(grid_type, space_set, null, null, range_sets, null);
FlatField grid =
new FlatField(grid_type, space_set);
grid.setSamples(data, false);
return grid;
}
public synchronized DataImpl open(URL url)
throws BadFormException, VisADException, IOException {
return open(url.toString());
}
public synchronized FormNode getForms(Data data) {
return null;
}
/** the width and height of the UI frame */
public static int WIDTH = 800;
public static int HEIGHT = 600;
/** run 'java visad.data.vis5d.Vis5DForm QLQ.v5d' to test */
public static void main(String args[])
throws VisADException, RemoteException, IOException {
if (args == null || args.length < 1) {
System.out.println("run 'java visad.data.vis5d.Vis5DForm file.v5d'");
}
Vis5DForm form = new Vis5DAdaptedForm();
FieldImpl vis5d = null;
try {
vis5d = (FieldImpl) form.open(args[0]);
DumpType.dumpMathType(vis5d.getType());
}
catch (Exception e) {
System.out.println(e.getMessage());
return;
}
if (vis5d == null) {
System.out.println("bad Vis5D file read");
return;
}
FunctionType type = (FunctionType) vis5d.getType();
FieldImpl new_vis5d;
if ( type.getRange() instanceof TupleType ) {
//-new_vis5d = (FieldImpl)vis5d.extract(20);
new_vis5d = vis5d;
}
else {
new_vis5d = vis5d;
}
FunctionType vis5d_type = (FunctionType) new_vis5d.getType();
System.out.println(vis5d_type);
DataReference vis5d_ref = new DataReferenceImpl("vis5d_ref");
vis5d_ref.setData(new_vis5d);
//
// construct JFC user interface with JSliders linked to
// Data objects, and embed Displays into JFC JFrame
//
// create a JFrame
JFrame frame = new JFrame("Vis5D");
WindowListener l = new WindowAdapter() {
public void windowClosing(WindowEvent e) {System.exit(0);}
};
frame.addWindowListener(l);
frame.setSize(WIDTH, HEIGHT);
frame.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
frame.setLocation(screenSize.width/2 - WIDTH/2,
screenSize.height/2 - HEIGHT/2);
// create big_panel JPanel in frame
JPanel big_panel = new JPanel();
big_panel.setLayout(new BoxLayout(big_panel, BoxLayout.X_AXIS));
big_panel.setAlignmentY(JPanel.TOP_ALIGNMENT);
big_panel.setAlignmentX(JPanel.LEFT_ALIGNMENT);
frame.getContentPane().add(big_panel);
// frame.setVisible(true);
// create left hand side JPanel for sliders and text
JPanel left = new JPanel(); // FlowLayout and double buffer
left.setLayout(new BoxLayout(left, BoxLayout.Y_AXIS));
left.setAlignmentY(JPanel.TOP_ALIGNMENT);
left.setAlignmentX(JPanel.LEFT_ALIGNMENT);
big_panel.add(left);
// construct JLabels
// (JTextArea does not align in BoxLayout well, so use JLabels)
left.add(new JLabel("Simple Vis5D File Viewer using VisAD - See:"));
left.add(new JLabel(" "));
left.add(new JLabel(" http://www.ssec.wisc.edu/~billh/visad.html"));
left.add(new JLabel(" "));
left.add(new JLabel("for more information about VisAD."));
left.add(new JLabel(" "));
left.add(new JLabel("Space Science and Engineering Center"));
left.add(new JLabel("University of Wisconsin - Madison"));
left.add(new JLabel(" "));
left.add(new JLabel(" "));
left.add(new JLabel("Move sliders to adjust iso-surface levels"));
left.add(new JLabel(" "));
left.add(new JLabel("Click Animate button to toggle animation"));
left.add(new JLabel(" "));
left.add(new JLabel("Rotate scenes with left mouse button."));
left.add(new JLabel(" "));
left.add(new JLabel(" "));
left.add(new JLabel(" "));
// create sliders JPanel
JPanel sliders = new JPanel();
sliders.setName("GoesRetrieval Sliders");
sliders.setFont(new Font("Dialog", Font.PLAIN, 12));
sliders.setLayout(new BoxLayout(sliders, BoxLayout.Y_AXIS));
sliders.setAlignmentY(JPanel.TOP_ALIGNMENT);
sliders.setAlignmentX(JPanel.LEFT_ALIGNMENT);
left.add(sliders);
// construct JPanel and sub-panels for Displays
JPanel display_panel = new JPanel();
display_panel.setLayout(new BoxLayout(display_panel,
BoxLayout.X_AXIS));
display_panel.setAlignmentY(JPanel.TOP_ALIGNMENT);
display_panel.setAlignmentX(JPanel.LEFT_ALIGNMENT);
big_panel.add(display_panel);
// create a Display and add it to panel
DisplayImpl display = new DisplayImplJ3D("image display");
GraphicsModeControl mode = display.getGraphicsModeControl();
mode.setScaleEnable(true);
display_panel.add(display.getComponent());
// extract RealType components from vis5d_type and use
// them to determine how data are displayed
// map time to Animation
RealType time = (RealType) vis5d_type.getDomain().getComponent(0);
ScalarMap animation_map = new ScalarMap(time, Display.Animation);
display.addMap(animation_map);
// default is ON
final AnimationControl animation_control =
(AnimationControl) animation_map.getControl();
// get grid type
/*
//-RealTupleType reference = (domain.getCoordinateSystem()).getReference();
// domain = reference;
// map grid coordinates to display coordinates
//-display.addMap(new ScalarMap((RealType) domain.getComponent(1),
display.addMap(new ScalarMap(RealType.getRealType("col"),
Display.XAxis));
//-display.addMap(new ScalarMap((RealType) domain.getComponent(0),
display.addMap(new ScalarMap(RealType.getRealType("row"),
Display.YAxis));
//-display.addMap(new ScalarMap((RealType) domain.getComponent(2),
display.addMap(new ScalarMap(RealType.getRealType("lev"),
Display.ZAxis));
*/
display.addMap(new ScalarMap(RealType.Latitude, Display.YAxis));
display.addMap(new ScalarMap(RealType.Longitude, Display.XAxis));
display.addMap(new ScalarMap(RealType.Altitude, Display.ZAxis));
// map grid values to IsoContour
int n_range_real_types = 0;
MathType v5d_range = vis5d_type.getRange();
RealType[] tmp = new RealType[200];
if ( v5d_range instanceof TupleType ) {
for ( int ii = 0; ii < ((TupleType)v5d_range).getDimension(); ii++) {
FunctionType f_type =
(FunctionType)
((TupleType)v5d_range).getComponent(ii);
MathType mtype = f_type.getRange();
if (mtype instanceof TupleType) {
int nn = ((TupleType)mtype).getDimension();
for ( int kk = 0; kk < nn; kk++) {
tmp[n_range_real_types++] = (RealType)((TupleType)mtype).getComponent(kk);
}
}
else {
tmp[n_range_real_types++] = (RealType)mtype;
}
}
}
else {
MathType mtype = ((FunctionType)v5d_range).getRange();
if (mtype instanceof TupleType) {
int nn = ((TupleType)mtype).getDimension();
for ( int kk = 0; kk < nn; kk++) {
tmp[n_range_real_types++] = (RealType)((TupleType)mtype).getComponent(kk);
}
}
else {
tmp[n_range_real_types++] = (RealType)mtype;
}
}
int dim = n_range_real_types;
RealType[] range_types = new RealType[dim];
ScalarMap[] contour_maps = new ScalarMap[dim];
ContourControl[] contour_controls = new ContourControl[dim];
DataReference[] range_refs = new DataReferenceImpl[dim];
for (int i=0; i<dim; i++) {
//-range_types[i] = (RealType) range.getComponent(i);
range_types[i] = (RealType) tmp[i];
contour_maps[i] = new ScalarMap(range_types[i], Display.IsoContour);
try {
display.addMap(contour_maps[i]);
contour_controls[i] = (ContourControl) contour_maps[i].getControl();
contour_controls[i].enableContours(false);
} catch (BadMappingException bme) {;} // handle case of duplicate names
range_refs[i] = new DataReferenceImpl(range_types[i].getName() + "_ref");
}
/* WLH - uncomment these for color demo images from the QLQ.v5d data set
ScalarMap color_map = new ScalarMap(range_types[1], Display.Green);
display.addMap(color_map);
color_map.setRange(23.5, 0.0);
display.addMap(new ConstantMap(0.5, Display.Red));
display.addMap(new ConstantMap(0.5, Display.Blue));
*/
// now Display vis5d data
display.addReference(vis5d_ref);
// wait for auto-scaling
boolean scaled = false;
double[][] ranges = new double[dim][];
while (!scaled) {
try {
Thread.sleep(1000);
}
catch (InterruptedException e) {
}
scaled = true;
for (int i=0; i<dim; i++) {
ranges[i] = contour_maps[i].getRange();
if (ranges[i][0] != ranges[i][0] ||
ranges[i][1] != ranges[i][1]) {
scaled = false;
// System.out.println("tick");
break;
}
}
}
for (int i=0; i<dim; i++) {
double scale = (ranges[i][1] - ranges[i][0]) / 255.0;
int low = (int) (ranges[i][0] / scale);
int hi = (int) (ranges[i][1] / scale);
range_refs[i].setData(new Real(range_types[i], scale * low));
sliders.add(new VisADSlider(range_types[i].getName(), low, hi, low, scale,
range_refs[i], range_types[i]));
sliders.add(new JLabel(" "));
ContourCell cell =
form. new ContourCell(contour_controls[i], range_refs[i]);
cell.addReference(range_refs[i]);
}
final JToggleButton button = new JToggleButton("Animate", false);
button.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent e) {
try {
// boolean state = ((ToggleButtonModel) button.getModel()).isSelected();
boolean state = button.getModel().isSelected();
animation_control.setOn(state);
}
catch (VisADException ee) {
}
catch (RemoteException ee) {
}
}
});
sliders.add(button);
// make the JFrame visible
frame.setVisible(true);
}
class ContourCell extends CellImpl {
ContourControl control;
DataReference ref;
double value;
ContourCell(ContourControl c, DataReference r)
throws VisADException, RemoteException {
control = c;
ref = r;
value = ((Real) ref.getData()).getValue();
}
public void doAction() throws VisADException, RemoteException {
double val = ((Real) ref.getData()).getValue();
if (val == val && val != value) {
control.setSurfaceValue((float) ((Real) ref.getData()).getValue());
control.enableContours(true);
value = val;
}
}
}
/* here's the output:
demedici% java visad.data.vis5d.Vis5DForm SCHL.v5d
FunctionType: (time) -> FunctionType (Real): (row, col, lev) -> (U, V, W, QL, TH, Q, P, ED, F)
demedici% java visad.data.vis5d.Vis5DForm QLQ.v5d
FunctionType: (time) -> FunctionType (Real): (row, col, lev) -> (QL, Q)
demedici%
*/
/** native method declarations */
/** calls v5dOpenFile in v5d.c */
/*
private native void v5d_open(byte[] name, int name_length, int[] sizes,
byte[] varnames, float[] times);
*/
/** calls v5dReadGrid in v5d.c */
/*
private native void v5d_read(int time, int var, float[] ranges, float[] data);
*/
}