Re: Variable Winds

Hi James,

> Thanks for the recommendation. I've gone for option 2, but have run into
> difficulty as described below.

Not exactly my recommendation (separate Data object and ScalarMap
to Shape), but good enough. You can fix the problem by adding:

  TextControl tcontrol = (TextControl) flows_text_map.getControl();
  tcontrol.setNumberFormat(new DecimalFormat());

after 'display.addMap(flows_text_map);', and 'import java.text.*;'
at the top. The default NumberFormat must deal with NaN incorrectly.
I attached a fixed version of your code.

Cheers,
Bill

> I'd like to embed new data (as per your suggestion) in the same tuple as
> the existing wind data, and also have the wind speed displayed as text
> on the screen.
>
> To do this, I'm thinking of a tuple like this:
> (lat,lon,(dir,speed),(variable_dir, variable_speed))
>
> To indicate a variable wind, the following sequence would occur:
> 1) user presses V
> 2) dir is set to NaN (and wind barb disappears from the screen)
> 3) variable_dir is set to the old value of dir (in case the user presses
> V again to turn off the variable direction we can restore dir to its
> original value).
> 4) variable_speed is set to speed
> 5) variable_speed has been mapped to Display.Text, and so the "variable"
> speed is displayed on the screen.
>
> This is pretty much what I want (and could optionally do a shape as
> well), but this isn't working for me.
>
> To illustrate the problem, I've modified visad.bom.BarbRendererJ3D
> (attached).
> In it, I've set "varable_speed" to NaN, and mapped this to Display.Text,
> and expect no text to appear on the display. However, if you run the
> code with:
> java visad.bom.BarbRendererJ3D 1 1
> you will see a "0" displayed alongside every wind barb.
>
> This problem doesn't occur with "speed", just with "variable_speed". To
> confirm this (correct) behaviour:
> * uncomment line 177:
>   // ScalarMap flows_text_map = new ScalarMap(flow_speed, Display.Text);
> * comment out line 179:
>   ScalarMap flows_text_map = new ScalarMap(flow_variable_speed,
> Display.Text
> * uncomment lines 218 and 219 which hardware "speed" to NaN:
>           // values[2][m] = Double.NaN;
>           // values[3][m] = Double.NaN;
>
> Then run the code again and you will see nothing displayed (ie no wind
> barbs and no text as expected).
>
> So why can't I make the text for "variable_speed" disappear by setting
> it to NaN?
>
> Cheers,
>
> James
>
>
>
>
>
> Bill Hibbard wrote:
> >
> > Hi James,
> >
> > ....
> > 2. An alternative is for your application to note where it wants
> > variable winds. It could set those wind components to NaN to
> > disable the usual barb rendering, and then create new Data with
> > a MathType something like:
> >
> >   (x, y, aux_speed)
> >
> > with the ScalarMaps:
> >
> >   x -> XAxis
> >   y -> YAxis
> >   aux_speed -> Shape
> >
> > and just create an array of shapes for the variable circles for
> > various speed values.
> >
>
> --
> James Kelly                                          Regional Computing
> Phone: 61-3-9669-4724 Fax: 61-3-9669-4128     Email: J.Kelly@xxxxxxxxxx
>
//
// BarbRendererJ3D.java
//

/*
VisAD system for interactive analysis and visualization of numerical
data.  Copyright (C) 1996 - 2002 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.bom;

import visad.*;
import visad.java3d.*;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
import java.rmi.*;
import java.text.*; // WLH


/**
   BarbRendererJ3D is the VisAD class for rendering of
   wind barbs under Java3D - otherwise it behaves just
   like DefaultRendererJ3D
*/
public class BarbRendererJ3D extends DefaultRendererJ3D
       implements BarbRenderer {

  private BarbManipulationRendererJ3D bmr;

  /** this DataRenderer supports direct manipulation for RealTuple
      representations of wind barbs; four of the RealTuple's Real
      components must be mapped to XAxis, YAxis, Flow1X and Flow1Y */
  public BarbRendererJ3D () {
    super();
    bmr = new BarbManipulationRendererJ3D();
  }

  public ShadowType makeShadowFunctionType(
         FunctionType type, DataDisplayLink link, ShadowType parent)
         throws VisADException, RemoteException {
    return new ShadowBarbFunctionTypeJ3D(type, link, parent);
  }

  public ShadowType makeShadowRealTupleType(
         RealTupleType type, DataDisplayLink link, ShadowType parent)
         throws VisADException, RemoteException {
    return new ShadowBarbRealTupleTypeJ3D(type, link, parent);
  }

  public ShadowType makeShadowRealType(
         RealType type, DataDisplayLink link, ShadowType parent)
         throws VisADException, RemoteException {
    return new ShadowBarbRealTypeJ3D(type, link, parent);
  }

  public ShadowType makeShadowSetType(
         SetType type, DataDisplayLink link, ShadowType parent)
         throws VisADException, RemoteException {
    return new ShadowBarbSetTypeJ3D(type, link, parent);
  }

  public ShadowType makeShadowTupleType(
         TupleType type, DataDisplayLink link, ShadowType parent)
         throws VisADException, RemoteException {
    return new ShadowBarbTupleTypeJ3D(type, link, parent);
  }

  public void setKnotsConvert(boolean enable) {
    bmr.setKnotsConvert(enable);
  } 
  
  public boolean getKnotsConvert() {
    return bmr.getKnotsConvert();
  } 

  public float[] makeVector(boolean south, float x, float y, float z,
                          float scale, float pt_size, float f0, float f1,
                          float[] vx, float[] vy, float[] vz, int[] numv,
                          float[] tx, float[] ty, float[] tz, int[] numt) { 
    return bmr.makeVector(south, x, y, z, scale, pt_size, f0, f1, vx, vy, vz,
                          numv, tx, ty, tz, numt);
  }

  public Object clone() {
    return new BarbRendererJ3D();
  }

  static final int N = 5;

  /** run 'java visad.bom.BarbRendererJ3D middle_latitude'
          to test with Cartesian winds
      run 'java visad.bom.BarbRendererJ3D middle_latitude x'
          to test with polar winds
      adjust middle_latitude for south or north barbs */
  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) { }
    }
    RealType lat = RealType.Latitude;
    RealType lon = RealType.Longitude;
    RealType flowx = RealType.getRealType("flowx",
                          CommonUnit.meterPerSecond);
    RealType flowy = RealType.getRealType("flowy",
                          CommonUnit.meterPerSecond);
    RealType red = RealType.getRealType("red");
    RealType green = RealType.getRealType("green");
    RealType index = RealType.getRealType("index");
    EarthVectorType flowxy = new EarthVectorType(flowx, flowy);
    TupleType range = null;
    RealType flow_degree = RealType.getRealType("flow_degree",
                          CommonUnit.degree);
    RealType flow_speed = RealType.getRealType("flow_speed",
                          CommonUnit.meterPerSecond);
    // jk start
    RealType flow_variable_degree = RealType.getRealType("flow_variable_degree",
                          CommonUnit.degree);
    RealType flow_variable_speed = RealType.getRealType("flow_variable_speed",
                          CommonUnit.meterPerSecond);
    // jk end
    if (args.length > 1) {
      System.out.println("polar winds");
      RealTupleType flowds =
        new RealTupleType(new RealType[] {flow_degree, flow_speed},
        new WindPolarCoordinateSystem(flowxy), null);
      // jk start
      RealTupleType flow_variable_ds =
        new RealTupleType(new RealType[] {flow_variable_degree, 
flow_variable_speed},
        new WindPolarCoordinateSystem(flowxy), null);
      // range = new TupleType(new MathType[] {lon, lat, flowds, red, green});
      range = new TupleType(new MathType[] {lon, lat, flowds, red, green, 
flow_variable_ds});
      // jk end
    }
    else {
      System.out.println("Cartesian winds");
      range = new TupleType(new MathType[] {lon, lat, flowxy, red, green});
    }
    FunctionType flow_field = new FunctionType(index, range);

    DisplayImpl display = new DisplayImplJ3D("display1");
    ScalarMap xmap = new ScalarMap(lon, Display.XAxis);
    display.addMap(xmap);
    ScalarMap ymap = new ScalarMap(lat, Display.YAxis);
    display.addMap(ymap);
    if (args.length > 1) {
      ScalarMap flowd_map = new ScalarMap(flow_degree, Display.Flow1Azimuth);
      display.addMap(flowd_map);
      flowd_map.setRange(0.0, 360.0);
      ScalarMap flows_map = new ScalarMap(flow_speed, Display.Flow1Radial);
      display.addMap(flows_map);
      flows_map.setRange(0.0, 1.0);
      // jk start
      // uncomment this line to give expected behaviour
      // ScalarMap flows_text_map = new ScalarMap(flow_speed, Display.Text);
      // but this line gives unexpected "0" everywhere when variable speed is 
NaN
      ScalarMap flows_text_map = new ScalarMap(flow_variable_speed, 
Display.Text);
      display.addMap(flows_text_map);
      // jk end

  TextControl tcontrol = (TextControl) flows_text_map.getControl(); // WLH
  tcontrol.setNumberFormat(new DecimalFormat()); // WLH

      FlowControl flow_control = (FlowControl) flows_map.getControl();
      flow_control.setFlowScale(0.1f);
    }
    else {
      ScalarMap flowx_map = new ScalarMap(flowx, Display.Flow1X);
      display.addMap(flowx_map);
      flowx_map.setRange(-1.0, 1.0);
      ScalarMap flowy_map = new ScalarMap(flowy, Display.Flow1Y);
      display.addMap(flowy_map);
      flowy_map.setRange(-1.0, 1.0);
      FlowControl flow_control = (FlowControl) flowy_map.getControl();
      flow_control.setFlowScale(0.1f);
    }
    display.addMap(new ScalarMap(red, Display.Red));
    display.addMap(new ScalarMap(green, Display.Green));
    display.addMap(new ConstantMap(1.0, Display.Blue));

    Integer1DSet set = new Integer1DSet(N * N);
    // jk start
    // double[][] values = new double[6][N * N];
    double[][] values = new double[8][N * N];
    // jk end
    int m = 0;
    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;
        values[0][m] = 10.0 * u;
        values[1][m] = 10.0 * v + mid_lat;
        double fx = 30.0 * u;
        double fy = 30.0 * v;
        if (args.length > 1) {
          values[2][m] =
            Data.RADIANS_TO_DEGREES * Math.atan2(-fx, -fy);
          values[3][m] = Math.sqrt(fx * fx + fy * fy);
          values[6][m] = Double.NaN;
          values[7][m] = Double.NaN;
        }
        else {
          values[2][m] = fx;
          values[3][m] = fy;
        }
        values[4][m] = u;
        values[5][m] = v;
        m++;
      }
    }
    FlatField field = new FlatField(flow_field, set);
    field.setSamples(values);
    DataReferenceImpl ref = new DataReferenceImpl("ref");
    ref.setData(field);
    BarbRendererJ3D renderer = new BarbRendererJ3D();
    renderer.setKnotsConvert(true);
    display.addReferences(renderer, ref);

    // create JFrame (i.e., a window) for display and slider
    JFrame frame = new JFrame("test BarbRendererJ3D");
    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);
  }

}