示例#1
0
文件: Test05.java 项目: tomw2/visad
  void setupServerData(LocalDisplay[] dpys) throws RemoteException, VisADException {
    RealType[] types = {RealType.Latitude, RealType.Longitude};
    RealTupleType earth_location = new RealTupleType(types);
    RealType vis_radiance = RealType.getRealType("vis_radiance");
    RealType ir_radiance = RealType.getRealType("ir_radiance");
    RealType[] types2 = {vis_radiance, ir_radiance};
    RealTupleType radiance = new RealTupleType(types2);
    FunctionType image_tuple = new FunctionType(earth_location, radiance);

    int size = 64;
    FlatField imaget1 = FlatField.makeField(image_tuple, size, false);

    dpys[0].addMap(new ScalarMap(RealType.Latitude, Display.YAxis));
    dpys[0].addMap(new ScalarMap(RealType.Longitude, Display.XAxis));
    dpys[0].addMap(new ScalarMap(ir_radiance, Display.Green));
    dpys[0].addMap(new ScalarMap(vis_radiance, Display.RGB));
    dpys[0].addMap(new ScalarMap(ir_radiance, Display.ZAxis));
    dpys[0].addMap(new ConstantMap(0.5, Display.Blue));
    dpys[0].addMap(new ConstantMap(0.5, Display.Red));
    ScalarMap map1contour;
    map1contour = new ScalarMap(vis_radiance, Display.IsoContour);
    dpys[0].addMap(map1contour);
    if (uneven) {
      ContourControl control = (ContourControl) map1contour.getControl();
      float[] levs = {10.0f, 12.0f, 14.0f, 16.0f, 24.0f, 32.0f, 40.0f};
      control.setLevels(levs, 15.0f, true);
      control.enableLabels(true);
    }

    DataReferenceImpl ref_imaget1 = new DataReferenceImpl("ref_imaget1");
    ref_imaget1.setData(imaget1);
    dpys[0].addReference(ref_imaget1, null);
  }
示例#2
0
  public static void main(String[] args) throws Exception {

    DisplayImpl display = new DisplayImplJ2D("display");
    display.getDisplayRenderer().setBoxOn(false);
    double[] matrix = display.getProjectionControl().getMatrix();
    matrix[0] = 1.25;
    matrix[3] = -1.25;
    display.getProjectionControl().setMatrix(matrix);
    display.addMap(new ScalarMap(RealType.YAxis, Display.YAxis));
    display.addMap(new ScalarMap(RealType.XAxis, Display.XAxis));
    float[][] values = new float[3][220];
    int l = 0;
    for (int x = 0; x < 11; x++) {
      for (int y = 0; y < 20; y++) {
        values[0][l] = -1.f + y / 10.f;
        values[1][l] = 1.f - x / 4.f;
        values[2][l] = l++;
      }
    }
    Gridded3DSet set = new Gridded3DSet(RealTupleType.SpatialCartesian3DTuple, values, l);
    ScalarMap shapeMap = new ScalarMap(RealType.ZAxis, Display.Shape);
    display.addMap(shapeMap);
    ShapeControl sc = (ShapeControl) shapeMap.getControl();
    sc.setShapeSet(new Integer1DSet(l));
    sc.setShapes(WeatherSymbols.getAllMetSymbols());
    sc.setScale(0.1f);
    DataReference ref = new DataReferenceImpl("ref");
    ref.setData(set);
    display.addReference(ref);
    JFrame frame = new JFrame("Weather Symbol Plot Test");
    frame.addWindowListener(
        new WindowAdapter() {
          public void windowClosing(WindowEvent e) {
            System.exit(0);
          }
        });
    frame.getContentPane().add(display.getComponent());
    frame.pack();
    frame.setSize(500, 500);
    frame.setVisible(true);
  }
示例#3
0
  /**
   * Construct a satellite display using the specified McIDAS map file, image source. The image can
   * be displayed on a 3D globe or on a flat rectillinear projection.
   *
   * @param mapFile location of the McIDAS map file (path or URL)
   * @param imageSource location of the image source (path or URL)
   * @param display3D if true, use 3D display, otherwise flat rectillinear
   * @param remap remap the image into a domain over North America
   */
  public SatDisplay(String mapFile, String imageSource, boolean display3D, boolean remap) {
    try {
      //  Read in the map file
      BaseMapAdapter baseMapAdapter;
      if (mapFile.indexOf("://") > 0) // URL specified
      {
        baseMapAdapter = new BaseMapAdapter(new URL(mapFile));
      } else // local disk file
      {
        baseMapAdapter = new BaseMapAdapter(mapFile);
      }

      // Create the display and set up the scalar maps to map
      // data to the display
      ScalarMap latMap; // latitude  -> YAxis
      ScalarMap lonMap; // longitude -> XAxis
      if (display3D) {
        display = new DisplayImplJ3D("display");
        latMap = new ScalarMap(RealType.Latitude, Display.Latitude);
        lonMap = new ScalarMap(RealType.Longitude, Display.Longitude);
      } else {
        display = new DisplayImplJ3D("display", new TwoDDisplayRendererJ3D());
        latMap = new ScalarMap(RealType.Latitude, Display.YAxis);
        lonMap = new ScalarMap(RealType.Longitude, Display.XAxis);
      }
      display.addMap(latMap);
      display.addMap(lonMap);

      // set the display to a global scale
      latMap.setRange(-90.0, 90.0);
      lonMap.setRange(-180.0, 180.0);

      // create a reference for the map line
      DataReference maplinesRef = new DataReferenceImpl("MapLines");
      maplinesRef.setData(baseMapAdapter.getData());

      // set the attributes of the map lines (color, location)
      ConstantMap[] maplinesConstantMap = new ConstantMap[4];
      maplinesConstantMap[0] = new ConstantMap(0., Display.Blue);
      maplinesConstantMap[1] = new ConstantMap(1., Display.Red);
      maplinesConstantMap[2] = new ConstantMap(0., Display.Green);
      maplinesConstantMap[3] = new ConstantMap(1.001, Display.Radius); // just above the image

      // read in the image
      AreaAdapter areaAdapter = new AreaAdapter(imageSource);
      FlatField image = areaAdapter.getData();

      // Extract the metadata from the image
      FunctionType imageFunctionType = (FunctionType) image.getType();
      RealTupleType imageDomainType = imageFunctionType.getDomain();
      RealTupleType imageRangeType = (RealTupleType) imageFunctionType.getRange();

      // remap and resample the image
      if (remap) {
        int SIZE = 256;
        RealTupleType latlonType =
            ((CoordinateSystem) imageDomainType.getCoordinateSystem()).getReference();
        Linear2DSet remapDomainSet =
            new Linear2DSet(latlonType, -4.0, 70.0, SIZE, -150.0, 5.0, SIZE);
        image = (FlatField) image.resample(remapDomainSet, Data.NEAREST_NEIGHBOR, Data.NO_ERRORS);
      }

      // select which band to show...
      ScalarMap rgbMap = new ScalarMap((RealType) imageRangeType.getComponent(0), Display.RGB);
      display.addMap(rgbMap);

      // set the enhancement to a grey scale
      ColorControl colorControl = (ColorControl) rgbMap.getControl();
      colorControl.initGreyWedge();

      // create a data reference for the image
      DataReferenceImpl imageRef = new DataReferenceImpl("ImageRef");
      imageRef.setData(image);

      // add the data references to the display
      display.disableAction();
      drmap = new DefaultRendererJ3D();
      drimage = new DefaultRendererJ3D();
      drmap.toggle(false);
      drimage.toggle(false);
      display.addDisplayListener(this);

      display.addReferences(drmap, maplinesRef, maplinesConstantMap);
      display.addReferences(drimage, imageRef, null);
      display.enableAction();
    } catch (Exception ne) {
      ne.printStackTrace();
      System.exit(1);
    }
  }
示例#4
0
  /**
   * transform data into a (Java3D or Java2D) scene graph; add generated scene graph components as
   * children of group; group is Group (Java3D) or VisADGroup (Java2D); value_array are inherited
   * valueArray values; default_values are defaults for each display.DisplayRealTypeVector; return
   * true if need post-process
   */
  public boolean doTransform(
      Object group,
      Data data,
      float[] value_array,
      float[] default_values,
      DataRenderer renderer,
      ShadowType shadow_api)
      throws VisADException, RemoteException {

    if (data.isMissing()) return false;
    if (LevelOfDifficulty == NOTHING_MAPPED) return false;

    if (!(data instanceof Text)) {
      throw new DisplayException("data must be Text: " + "ShadowTextType.doTransform");
    }

    // get some precomputed values useful for transform
    // length of ValueArray
    int valueArrayLength = display.getValueArrayLength();
    // mapping from ValueArray to DisplayScalar
    int[] valueToScalar = display.getValueToScalar();
    // mapping from ValueArray to MapVector
    int[] valueToMap = display.getValueToMap();
    Vector MapVector = display.getMapVector();

    // array to hold values for various mappings
    float[][] display_values = new float[valueArrayLength][];

    // ????
    // get values inherited from parent;
    // assume these do not include SelectRange, SelectValue
    // or Animation values - see temporary hack in
    // DataRenderer.isTransformControl
    int[] inherited_values = getInheritedValues();
    for (int i = 0; i < valueArrayLength; i++) {
      if (inherited_values[i] > 0) {
        display_values[i] = new float[1];
        display_values[i][0] = value_array[i];
      }
    }

    boolean[][] range_select =
        shadow_api.assembleSelect(
            display_values, 1, valueArrayLength, valueToScalar, display, shadow_api);

    if (range_select[0] != null && !range_select[0][0]) {
      // data not selected
      return false;
    }

    // get any text String and TextControl inherited from parent
    String text_value = shadow_api.getParentText();
    TextControl text_control = shadow_api.getParentTextControl();
    boolean anyText = getAnyText();
    if (anyText && text_value == null) {
      // get any text String and TextControl from this
      Vector maps = getSelectedMapVector();
      if (!maps.isEmpty()) {
        text_value = ((Text) data).getValue();
        ScalarMap map = (ScalarMap) maps.firstElement();
        text_control = (TextControl) map.getControl();
      }
    }

    //
    // never renders text ????
    //

    // add values to value_array according to SelectedMapVector
    if (getIsTerminal()) {
      // ????
      return terminalTupleOrScalar(
          group,
          display_values,
          text_value,
          text_control,
          valueArrayLength,
          valueToScalar,
          default_values,
          inherited_values,
          renderer,
          shadow_api);
    } else {
      // nothing to render at a non-terminal TextType
    }
    return false;
  }
  /** test BarbManipulationRendererJ3D */
  public static void main(String args[]) throws VisADException, RemoteException {

    System.out.println("BMR.main()");

    // construct RealTypes for wind record components
    RealType lat = RealType.Latitude;
    RealType lon = RealType.Longitude;
    RealType windx = RealType.getRealType("windx", CommonUnit.meterPerSecond);
    RealType windy = RealType.getRealType("windy", CommonUnit.meterPerSecond);
    RealType red = RealType.getRealType("red");
    RealType green = RealType.getRealType("green");

    // EarthVectorType extends RealTupleType and says that its
    // components are vectors in m/s with components parallel
    // to Longitude (positive east) and Latitude (positive north)
    EarthVectorType windxy = new EarthVectorType(windx, windy);

    RealType wind_dir = RealType.getRealType("wind_dir", CommonUnit.degree);
    RealType wind_speed = RealType.getRealType("wind_speed", CommonUnit.meterPerSecond);
    RealTupleType windds = null;
    if (args.length > 0) {
      System.out.println("polar winds");
      windds =
          new RealTupleType(
              new RealType[] {wind_dir, wind_speed}, new WindPolarCoordinateSystem(windxy), null);
    }

    // construct Java3D display and mappings that govern
    // how wind records are displayed
    DisplayImpl display = new DisplayImplJ3D("display1", new TwoDDisplayRendererJ3D());
    ScalarMap lonmap = new ScalarMap(lon, Display.XAxis);
    display.addMap(lonmap);
    ScalarMap latmap = new ScalarMap(lat, Display.YAxis);
    display.addMap(latmap);

    FlowControl flow_control;
    if (args.length > 0) {
      ScalarMap winds_map = new ScalarMap(wind_speed, Display.Flow1Radial);
      display.addMap(winds_map);
      winds_map.setRange(0.0, 1.0); // do this for barb rendering
      ScalarMap windd_map = new ScalarMap(wind_dir, Display.Flow1Azimuth);
      display.addMap(windd_map);
      windd_map.setRange(0.0, 360.0); // do this for barb rendering
      flow_control = (FlowControl) windd_map.getControl();
      flow_control.setFlowScale(0.15f); // this controls size of barbs
    } else {
      ScalarMap windx_map = new ScalarMap(windx, Display.Flow1X);
      display.addMap(windx_map);
      windx_map.setRange(-1.0, 1.0); // do this for barb rendering
      ScalarMap windy_map = new ScalarMap(windy, Display.Flow1Y);
      display.addMap(windy_map);
      windy_map.setRange(-1.0, 1.0); // do this for barb rendering
      flow_control = (FlowControl) windy_map.getControl();
      flow_control.setFlowScale(0.15f); // this controls size of barbs
    }

    display.addMap(new ScalarMap(red, Display.Red));
    display.addMap(new ScalarMap(green, Display.Green));
    display.addMap(new ConstantMap(1.0, Display.Blue));

    DataReferenceImpl[] refs = new DataReferenceImpl[N * N];
    int k = 0;
    // create an array of N by N winds
    for (int i = 0; i < N; i++) {
      for (int j = 0; j < N; j++) {
        double u = 2.0 * i / (N - 1.0) - 1.0;
        double v = 2.0 * j / (N - 1.0) - 1.0;

        // each wind record is a Tuple (lon, lat, (windx, windy), red, green)
        // set colors by wind components, just for grins
        Tuple tuple;
        double fx = 30.0 * u;
        double fy = 30.0 * v;
        if (args.length > 0) {
          double fd = Data.RADIANS_TO_DEGREES * Math.atan2(-fx, -fy);
          double fs = Math.sqrt(fx * fx + fy * fy);
          tuple =
              new Tuple(
                  new Data[] {
                    new Real(lon, 10.0 * u),
                    new Real(lat, 10.0 * v - 40.0),
                    new RealTuple(windds, new double[] {fd, fs}),
                    new Real(red, u),
                    new Real(green, v)
                  });
        } else {
          tuple =
              new Tuple(
                  new Data[] {
                    new Real(lon, 10.0 * u),
                    new Real(lat, 10.0 * v - 40.0),
                    new RealTuple(windxy, new double[] {fx, fy}),
                    new Real(red, u),
                    new Real(green, v)
                  });
        }

        // construct reference for wind record
        refs[k] = new DataReferenceImpl("ref_" + k);
        refs[k].setData(tuple);

        // link wind record to display via BarbManipulationRendererJ3D
        // so user can change barb by dragging it
        // drag with right mouse button and shift to change direction
        // drag with right mouse button and no shift to change speed
        BarbManipulationRendererJ3D renderer = new BarbManipulationRendererJ3D();
        renderer.setKnotsConvert(true);
        display.addReferences(renderer, refs[k]);

        // link wind record to a CellImpl that will listen for changes
        // and print them
        WindGetterJ3D cell = new WindGetterJ3D(flow_control, refs[k]);
        cell.addReference(refs[k]);

        k++;
      }
    }

    // instead of linking the wind record "DataReferenceImpl refs" to
    // the WindGetterJ3Ds, you can have some user interface event (e.g.,
    // the user clicks on "DONE") trigger code that does a getData() on
    // all the refs and stores the records in a file.

    // create JFrame (i.e., a window) for display and slider
    JFrame frame = new JFrame("test BarbManipulationRendererJ3D");
    frame.addWindowListener(
        new WindowAdapter() {
          public void windowClosing(WindowEvent e) {
            System.exit(0);
          }
        });

    // create JPanel in JFrame
    JPanel panel = new JPanel();
    panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
    panel.setAlignmentY(JPanel.TOP_ALIGNMENT);
    panel.setAlignmentX(JPanel.LEFT_ALIGNMENT);
    frame.getContentPane().add(panel);

    // add display to JPanel
    panel.add(display.getComponent());

    // set size of JFrame and make it visible
    frame.setSize(500, 500);
    frame.setVisible(true);
  }
示例#6
0
  /**
   * run 'java FlowTest middle_latitude' to test with (lat, lon) run 'java FlowTest middle_latitude
   * x' to test with (lon, lat) adjust middle_latitude for south or north
   */
  public static void main(String args[]) throws VisADException, RemoteException {
    double mid_lat = -10.0;
    if (args.length > 0) {
      try {
        mid_lat = Double.valueOf(args[0]).doubleValue();
      } catch (NumberFormatException e) {
      }
    }
    boolean swap = (args.length > 1);
    RealType lat = RealType.Latitude;
    RealType lon = RealType.Longitude;
    RealType[] types;
    if (swap) {
      types = new RealType[] {lon, lat};
    } else {
      types = new RealType[] {lat, lon};
    }
    RealTupleType earth_location = new RealTupleType(types);
    System.out.println("earth_location = " + earth_location + " mid_lat = " + mid_lat);

    RealType flowx = RealType.getRealType("flowx", CommonUnit.meterPerSecond);
    RealType flowy = RealType.getRealType("flowy", CommonUnit.meterPerSecond);
    RealType red = RealType.getRealType("red");
    RealType green = RealType.getRealType("green");
    EarthVectorType flowxy = new EarthVectorType(flowx, flowy);
    TupleType range = null;

    range = new TupleType(new MathType[] {flowxy, red, green});
    FunctionType flow_field = new FunctionType(earth_location, range);

    DisplayImpl display = new DisplayImplJ3D("display1", new TwoDDisplayRendererJ3D());
    ScalarMap xmap = new ScalarMap(lon, Display.XAxis);
    display.addMap(xmap);
    ScalarMap ymap = new ScalarMap(lat, Display.YAxis);
    display.addMap(ymap);
    ScalarMap flowx_map = new ScalarMap(flowx, Display.Flow1X);
    display.addMap(flowx_map);
    flowx_map.setRange(-10.0, 10.0);
    ScalarMap flowy_map = new ScalarMap(flowy, Display.Flow1Y);
    display.addMap(flowy_map);
    flowy_map.setRange(-10.0, 10.0);
    FlowControl flow_control = (FlowControl) flowy_map.getControl();
    flow_control.setFlowScale(0.05f);
    display.addMap(new ScalarMap(red, Display.Red));
    display.addMap(new ScalarMap(green, Display.Green));
    display.addMap(new ConstantMap(1.0, Display.Blue));

    double lonlow = -10.0;
    double lonhi = 10.0;
    double latlow = mid_lat - 10.0;
    double lathi = mid_lat + 10.0;
    Linear2DSet set;
    if (swap) {
      set = new Linear2DSet(earth_location, lonlow, lonhi, N, latlow, lathi, N);
    } else {
      set = new Linear2DSet(earth_location, latlow, lathi, N, lonlow, lonhi, N);
    }
    double[][] values = new double[4][N * N];
    int m = 0;
    for (int i = 0; i < N; i++) {
      for (int j = 0; j < N; j++) {
        int k = i;
        int l = j;
        if (swap) {
          k = j;
          l = i;
        }
        double u = (N - 1.0) / 2.0 - l;
        double v = k - (N - 1.0) / 2.0;
        // double u = 2.0 * k / (N - 1.0) - 1.0;
        // double v = 2.0 * l / (N - 1.0);
        double fx = 6.0 * u;
        double fy = 6.0 * v;
        values[0][m] = fx;
        values[1][m] = fy;
        values[2][m] = u;
        values[3][m] = v;
        m++;
      }
    }
    FlatField field = new FlatField(flow_field, set);
    field.setSamples(values);
    DataReferenceImpl ref = new DataReferenceImpl("ref");
    ref.setData(field);
    display.addReference(ref);

    // create JFrame (i.e., a window) for display and slider
    JFrame frame = new JFrame("test FlowTest");
    frame.addWindowListener(
        new WindowAdapter() {
          public void windowClosing(WindowEvent e) {
            System.exit(0);
          }
        });

    // create JPanel in JFrame
    JPanel panel = new JPanel();
    panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
    panel.setAlignmentY(JPanel.TOP_ALIGNMENT);
    panel.setAlignmentX(JPanel.LEFT_ALIGNMENT);
    frame.getContentPane().add(panel);

    // add display to JPanel
    panel.add(display.getComponent());

    // set size of JFrame and make it visible
    frame.setSize(500, 500);
    frame.setVisible(true);
  }
示例#7
0
文件: Test61.java 项目: tomw2/visad
  void setupServerData(LocalDisplay[] dpys) throws RemoteException, VisADException {
    RealType xr = RealType.getRealType("xr");
    RealType yr = RealType.getRealType("yr");
    RealType zr = RealType.getRealType("zr");
    RealType wr = RealType.getRealType("wr");
    RealType[] types3d = {xr, yr, zr};
    RealTupleType earth_location3d = new RealTupleType(types3d);
    FunctionType grid_tuple = new FunctionType(earth_location3d, wr);

    // int NX = 32;
    // int NY = 32;
    // int NZ = 32;
    int NX = 35;
    int NY = 35;
    int NZ = 35;
    Integer3DSet set = new Integer3DSet(NX, NY, NZ);
    FlatField grid3d = new FlatField(grid_tuple, set);

    float[][] values = new float[1][NX * NY * NZ];
    int k = 0;
    for (int iz = 0; iz < NZ; iz++) {
      // double z = Math.PI * (-1.0 + 2.0 * iz / (NZ - 1.0));
      double z = Math.PI * (-1.0 + 2.0 * iz * iz / ((NZ - 1.0) * (NZ - 1.0)));
      for (int iy = 0; iy < NY; iy++) {
        double y = -1.0 + 2.0 * iy / (NY - 1.0);
        for (int ix = 0; ix < NX; ix++) {
          double x = -1.0 + 2.0 * ix / (NX - 1.0);
          double r = x - 0.5 * Math.cos(z);
          double s = y - 0.5 * Math.sin(z);
          double dist = Math.sqrt(r * r + s * s);
          values[0][k] = (float) ((dist < 0.1) ? 10.0 : 1.0 / dist);
          k++;
        }
      }
    }
    grid3d.setSamples(values);

    dpys[0].addMap(new ScalarMap(xr, Display.XAxis));
    dpys[0].addMap(new ScalarMap(yr, Display.YAxis));
    dpys[0].addMap(new ScalarMap(zr, Display.ZAxis));

    ScalarMap xrange = new ScalarMap(xr, Display.SelectRange);
    ScalarMap yrange = new ScalarMap(yr, Display.SelectRange);
    ScalarMap zrange = new ScalarMap(zr, Display.SelectRange);
    dpys[0].addMap(xrange);
    dpys[0].addMap(yrange);
    dpys[0].addMap(zrange);

    GraphicsModeControl mode = dpys[0].getGraphicsModeControl();
    mode.setScaleEnable(true);

    if (nice) mode.setTransparencyMode(DisplayImplJ3D.NICEST);
    mode.setTexture3DMode(texture3DMode);

    // new
    RealType duh = RealType.getRealType("duh");
    int NT = 32;
    Linear2DSet set2 = new Linear2DSet(0.0, (double) NX, NT, 0.0, (double) NY, NT);
    RealType[] types2d = {xr, yr};
    RealTupleType domain2 = new RealTupleType(types2d);
    FunctionType ftype2 = new FunctionType(domain2, duh);
    float[][] v2 = new float[1][NT * NT];
    for (int i = 0; i < NT * NT; i++) {
      v2[0][i] = (i * i) % (NT / 2 + 3);
    }
    // float[][] v2 = {{1.0f,2.0f,3.0f,4.0f}};
    FlatField field2 = new FlatField(ftype2, set2);
    field2.setSamples(v2);
    dpys[0].addMap(new ScalarMap(duh, Display.RGB));

    ScalarMap map1color = new ScalarMap(wr, Display.RGBA);
    dpys[0].addMap(map1color);

    ColorAlphaControl control = (ColorAlphaControl) map1color.getControl();
    control.setTable(buildTable(control.getTable()));

    DataReferenceImpl ref_grid3d = new DataReferenceImpl("ref_grid3d");
    ref_grid3d.setData(grid3d);

    DataReferenceImpl ref2 = new DataReferenceImpl("ref2");
    ref2.setData(field2);

    ConstantMap[] cmaps = {new ConstantMap(0.0, Display.TextureEnable)};
    dpys[0].addReference(ref2, cmaps);

    dpys[0].addReference(ref_grid3d, null);
  }
  /**
   * run 'java visad.bom.ImageRendererJ3D len step' to test animation behavior of ImageRendererJ3D
   * renders a loop of len at step ms per frame then updates loop by deleting first time and adding
   * a new last time
   */
  public static void main(String args[]) throws VisADException, RemoteException, IOException {

    int step = 1000;
    int len = 3;
    if (args.length > 0) {
      try {
        len = Integer.parseInt(args[0]);
      } catch (NumberFormatException e) {
        len = 3;
      }
    }
    if (len < 1) len = 1;
    if (args.length > 1) {
      try {
        step = Integer.parseInt(args[1]);
      } catch (NumberFormatException e) {
        step = 1000;
      }
    }
    if (step < 1) step = 1;

    // create a netCDF reader
    Plain plain = new Plain();

    // open a netCDF file containing an image sequence and adapt
    // it to a Field Data object
    Field raw_image_sequence = null;
    try {
      // raw_image_sequence = (Field) plain.open("images256x256.nc");
      raw_image_sequence = (Field) plain.open("images.nc");
    } catch (IOException exc) {
      String s =
          "To run this example, the images.nc file must be "
              + "present in\nthe current directory."
              + "You can obtain this file from:\n"
              + "  ftp://www.ssec.wisc.edu/pub/visad-2.0/images.nc.Z";
      System.out.println(s);
      System.exit(0);
    }

    // just take first half of raw_image_sequence
    FunctionType image_sequence_type = (FunctionType) raw_image_sequence.getType();
    Set raw_set = raw_image_sequence.getDomainSet();
    float[][] raw_times = raw_set.getSamples();
    int raw_len = raw_times[0].length;
    if (raw_len != 4) {
      throw new VisADException("wrong number of images in sequence");
    }
    float raw_span = (4.0f / 3.0f) * (raw_times[0][3] - raw_times[0][0]);

    double[][] times = new double[1][len];
    for (int i = 0; i < len; i++) {
      times[0][i] = raw_times[0][i % raw_len] + raw_span * (i / raw_len);
    }
    Gridded1DDoubleSet set = new Gridded1DDoubleSet(raw_set.getType(), times, len);
    Field image_sequence = new FieldImpl(image_sequence_type, set);
    for (int i = 0; i < len; i++) {
      image_sequence.setSample(i, raw_image_sequence.getSample(i % raw_len));
    }

    // create a DataReference for image sequence
    final DataReference image_ref = new DataReferenceImpl("image");
    image_ref.setData(image_sequence);

    // create a Display using Java3D
    DisplayImpl display = new DisplayImplJ3D("image display");

    // extract the type of image and use
    // it to determine how images are displayed
    FunctionType image_type = (FunctionType) image_sequence_type.getRange();
    RealTupleType domain_type = image_type.getDomain();
    // map image coordinates to display coordinates
    display.addMap(new ScalarMap((RealType) domain_type.getComponent(0), Display.XAxis));
    display.addMap(new ScalarMap((RealType) domain_type.getComponent(1), Display.YAxis));
    // map image brightness values to RGB (default is grey scale)
    display.addMap(new ScalarMap((RealType) image_type.getRange(), Display.RGB));
    RealType hour_type = (RealType) image_sequence_type.getDomain().getComponent(0);
    ScalarMap animation_map = new ScalarMap(hour_type, Display.Animation);
    display.addMap(animation_map);
    AnimationControl animation_control = (AnimationControl) animation_map.getControl();
    animation_control.setStep(step);
    animation_control.setOn(true);

    /*
        // link the Display to image_ref
        ImageRendererJ3D renderer = new ImageRendererJ3D();
        display.addReferences(renderer, image_ref);
        // display.addReference(image_ref);
    */

    // create JFrame (i.e., a window) for display and slider
    JFrame frame = new JFrame("ImageRendererJ3D test");
    frame.addWindowListener(
        new WindowAdapter() {
          public void windowClosing(WindowEvent e) {
            System.exit(0);
          }
        });

    // create JPanel in JFrame
    JPanel panel = new JPanel();
    panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
    panel.setAlignmentY(JPanel.TOP_ALIGNMENT);
    panel.setAlignmentX(JPanel.LEFT_ALIGNMENT);
    frame.getContentPane().add(panel);

    // add display to JPanel
    panel.add(display.getComponent());

    // set size of JFrame and make it visible
    frame.setSize(500, 500);
    frame.setVisible(true);

    System.out.println("first animation sequence");
    // link the Display to image_ref
    ImageRendererJ3D renderer = new ImageRendererJ3D();
    display.addReferences(renderer, image_ref);
    // display.addReference(image_ref);

    // wait 4 * len seconds
    new Delay(len * 4000);

    // substitute a new image sequence for the old one
    for (int i = 0; i < len; i++) {
      times[0][i] = raw_times[0][(i + 1) % raw_len] + raw_span * ((i + 1) / raw_len);
    }
    set = new Gridded1DDoubleSet(raw_set.getType(), times, len);
    FieldImpl new_image_sequence = new FieldImpl(image_sequence_type, set);
    for (int i = 0; i < len; i++) {
      new_image_sequence.setSample(i, raw_image_sequence.getSample((i + 1) % raw_len));
    }

    System.out.println("second animation sequence");

    // tell renderer to resue frames in its scene graph
    renderer.setReUseFrames(true);
    image_ref.setData(new_image_sequence);
  }